WebDevice suite
This commit is contained in:
parent
212e0151fa
commit
33b57d7e67
|
|
@ -5,7 +5,7 @@ process.on('message',data => {
|
||||||
switch(data.type)
|
switch(data.type)
|
||||||
{
|
{
|
||||||
case "CLIENT_CREATED":{
|
case "CLIENT_CREATED":{
|
||||||
slog("CLIENT_CREATED");
|
//slog("CLIENT_CREATED");
|
||||||
let client = new Client();
|
let client = new Client();
|
||||||
client.isProxy = true;
|
client.isProxy = true;
|
||||||
client.proxyProcess = data.pid;
|
client.proxyProcess = data.pid;
|
||||||
|
|
@ -22,7 +22,7 @@ process.on('message',data => {
|
||||||
|
|
||||||
data.value = transformDeserialization(data.value, data.typing);
|
data.value = transformDeserialization(data.value, data.typing);
|
||||||
|
|
||||||
slog("CLIENT_UPDATE_PROP");
|
//slog("CLIENT_UPDATE_PROP");
|
||||||
let client = Client.clients.get(data.uuid);
|
let client = Client.clients.get(data.uuid);
|
||||||
client[data.name] = data.value;
|
client[data.name] = data.value;
|
||||||
break;
|
break;
|
||||||
|
|
@ -44,7 +44,7 @@ process.on('message',data => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "CLIENT_DESTROY":{
|
case "CLIENT_DESTROY":{
|
||||||
slog("CLIENT_DESTROY");
|
//slog("CLIENT_DESTROY");
|
||||||
if(Client.clients.has(data.uuid))
|
if(Client.clients.has(data.uuid))
|
||||||
{
|
{
|
||||||
Client.clients.delete(data.uuid);
|
Client.clients.delete(data.uuid);
|
||||||
|
|
@ -54,7 +54,7 @@ process.on('message',data => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "ROOM_CREATED":{
|
case "ROOM_CREATED":{
|
||||||
slog("ROOM_CREATED");
|
//slog("ROOM_CREATED");
|
||||||
let room = Room.fromJSON(data.value);
|
let room = Room.fromJSON(data.value);
|
||||||
Room.rooms.set(room.id, room);
|
Room.rooms.set(room.id, room);
|
||||||
break;
|
break;
|
||||||
|
|
@ -64,13 +64,13 @@ process.on('message',data => {
|
||||||
data.value = transformDeserialization(data.value, data.typing);
|
data.value = transformDeserialization(data.value, data.typing);
|
||||||
|
|
||||||
|
|
||||||
slog("ROOM_UPDATE_PROP");
|
//slog("ROOM_UPDATE_PROP");
|
||||||
let room = Room.rooms.get(data.uuid);
|
let room = Room.rooms.get(data.uuid);
|
||||||
room[data.name] = data.value;
|
room[data.name] = data.value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "ROOM_JOIN_CLIENT":{
|
case "ROOM_JOIN_CLIENT":{
|
||||||
slog("ROOM_JOIN_CLIENT");
|
//slog("ROOM_JOIN_CLIENT");
|
||||||
let room = Room.rooms.get(data.uuid);
|
let room = Room.rooms.get(data.uuid);
|
||||||
let client = Client.clients.get(data.client);
|
let client = Client.clients.get(data.client);
|
||||||
if(room && client)
|
if(room && client)
|
||||||
|
|
@ -81,7 +81,7 @@ process.on('message',data => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "ROOM_EJECT_CLIENT":{
|
case "ROOM_EJECT_CLIENT":{
|
||||||
slog("ROOM_EJECT_CLIENT");
|
//slog("ROOM_EJECT_CLIENT");
|
||||||
let room = Room.rooms.get(data.uuid);
|
let room = Room.rooms.get(data.uuid);
|
||||||
let client = Client.clients.get(data.client);
|
let client = Client.clients.get(data.client);
|
||||||
if(room && client)
|
if(room && client)
|
||||||
|
|
@ -92,7 +92,7 @@ process.on('message',data => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "ROOM_DESTROY":{
|
case "ROOM_DESTROY":{
|
||||||
slog("ROOM_DESTROY");
|
//slog("ROOM_DESTROY");
|
||||||
Room.rooms.delete(data.value);
|
Room.rooms.delete(data.value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import WebRTC from "./WebRTC";
|
import WebRTC from "./WebRTC";
|
||||||
import Peer from "./Peer";
|
import Peer from "./Peer";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deneyseldir kullanılması önerilmez
|
||||||
|
*/
|
||||||
export default class P2PFileSender
|
export default class P2PFileSender
|
||||||
{
|
{
|
||||||
public rtc : RTCPeerConnection;
|
public rtc : RTCPeerConnection;
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ export default class WebRTC
|
||||||
rtcpMuxPolicy:"require",
|
rtcpMuxPolicy:"require",
|
||||||
};
|
};
|
||||||
|
|
||||||
public isPolite() : boolean
|
private isPolite() : boolean
|
||||||
{
|
{
|
||||||
let myId = this.peer?.mwse.peer('me').socketId as string;
|
let myId = this.peer?.mwse.peer('me').socketId as string;
|
||||||
let peerId = this.peer?.socketId as string;
|
let peerId = this.peer?.socketId as string;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
import "./studio/window.js";
|
||||||
|
import { InputDevicesWindow } from "./studio/InputDevices.js";
|
||||||
|
import { Rooms } from "./studio/Rooms.js";
|
||||||
|
|
||||||
|
let mwse = new MWSE({
|
||||||
|
endpoint: "ws://localhost:7707"
|
||||||
|
});
|
||||||
|
|
||||||
|
mwse.scope(beginEngine);
|
||||||
|
|
||||||
|
async function beginEngine()
|
||||||
|
{
|
||||||
|
let me = await mwse.virtualPressure.allocAPIPAddress();
|
||||||
|
$(".network-id").text(me);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.openInputDevicesWindow = () => {
|
||||||
|
InputDevicesWindow.toggle();
|
||||||
|
InputDevicesWindow.bringToFront();
|
||||||
|
};
|
||||||
|
|
||||||
|
window.openRoomsWindow = () => {
|
||||||
|
Rooms.toggle();
|
||||||
|
Rooms.bringToFront();
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>MWSE UI 24.3 Studio</title>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.7/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container" style="max-width: 1200px;padding-top: 125px">
|
||||||
|
|
||||||
|
<h2 class="text-center">
|
||||||
|
MWSE UI 24.3
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<h1 class="text-center mb-5 mt-3 text-bold fw-bold">
|
||||||
|
<span>Ağ Adresiniz</span>
|
||||||
|
<span class="text-danger network-id">
|
||||||
|
#.#.#.#
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="position:fixed;left:0;right:0;bottom:0;background-color: rgba(0,0,0,.1);display: flex;flex-direction: row;gap: 5px">
|
||||||
|
<span class="bg-white d-inline-block m-1">
|
||||||
|
<button class="btn btn-outline-primary" onclick="openInputDevicesWindow()">
|
||||||
|
Giriş Aygıtları
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
<!--span class="bg-white d-inline-block m-1">
|
||||||
|
<button class="btn btn-outline-primary" onclick="openOutputDevicesWindow()">
|
||||||
|
Çıkış Aygıtları
|
||||||
|
</button>
|
||||||
|
</span-->
|
||||||
|
<span class="bg-white d-inline-block m-1">
|
||||||
|
<button class="btn btn-outline-primary" onclick="openRoomsWindow()">
|
||||||
|
Odalar
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
<span class="bg-white d-inline-block m-1">
|
||||||
|
<button class="btn btn-outline-primary" onclick="openPeersWindow()">
|
||||||
|
Cihazlar
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<script src="https://ws.saqut.com/script"></script>
|
||||||
|
<script src="./core.js" type="module"></script>
|
||||||
|
<style>
|
||||||
|
html,body{
|
||||||
|
margin: 0;
|
||||||
|
height: 100%;
|
||||||
|
background-image: url(./studio/background.jpg);
|
||||||
|
background-position: center center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
*{
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
* {
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: #7a7a7a #1e1e1e;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-track {
|
||||||
|
background: #1e1e1e;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #7a7a7a;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color: #aaaaaa;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,398 @@
|
||||||
|
import DWindow from "./window.js";
|
||||||
|
import { AddCell, FilterCell, memory, RemoveCell } from "./sdb.js";
|
||||||
|
|
||||||
|
export const InputDevicesWindow = new class InputDevicesWindow extends DWindow{
|
||||||
|
constructor(){
|
||||||
|
super();
|
||||||
|
this.initContent();
|
||||||
|
this.headtext.text("Giriş Aygıtları");
|
||||||
|
this.hide();
|
||||||
|
this.panel.css("min-width","640px");
|
||||||
|
this.panel.css("min-height","250px");
|
||||||
|
this.panel.css("width","max-content");
|
||||||
|
this.initEvent();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @type {JQuery<HTMLElement>}
|
||||||
|
*/
|
||||||
|
table = null;
|
||||||
|
initContent(){
|
||||||
|
this.table = $(`
|
||||||
|
<table class="table table-sm table-bordered table-striped text-nowrap">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Cihaz Türü</th>
|
||||||
|
<th>Sağlanan Kanallar</th>
|
||||||
|
<th>Akış ID</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td colspan="4">
|
||||||
|
<button class="btn btn-success w-100 newdevice">
|
||||||
|
Yeni Giriş Cihazı Ekle
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
`);
|
||||||
|
|
||||||
|
this.updateDevices();
|
||||||
|
|
||||||
|
this.content.append(this.table);
|
||||||
|
}
|
||||||
|
initEvent(){
|
||||||
|
this.content.find(".newdevice").on('click', this.generateDevice.bind(this));
|
||||||
|
this.addEventListener("close",()=>{
|
||||||
|
this.hide();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
updateDevices(){
|
||||||
|
let tbody = this.table.find("tbody");
|
||||||
|
tbody.text('');
|
||||||
|
for (const cell of FilterCell("rawstream", () => true))
|
||||||
|
{
|
||||||
|
let tr = $(`
|
||||||
|
<tr class="text-nowrap">
|
||||||
|
<td>${cell.source}</td>
|
||||||
|
<td>${cell.kind}</td>
|
||||||
|
<td>${cell.payload.id}</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-outline-primary action-view">Görüntüle</button>
|
||||||
|
<button class="btn btn-outline-danger action-close">Kapat</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`);
|
||||||
|
tr.attr("data-declare", cell.payload.id);
|
||||||
|
cell.addEventListener("stop",() => tr.remove());
|
||||||
|
tbody.append(tr);
|
||||||
|
}
|
||||||
|
tbody.find(".action-view").on('click', e => this.viewSource($(e.target)));
|
||||||
|
tbody.find(".action-close").on('click', e => this.closeSource($(e.target)));
|
||||||
|
}
|
||||||
|
closeSource(btn){
|
||||||
|
let streamid = btn.closest("tr").attr("data-declare");
|
||||||
|
for (const brain of FilterCell("rawstream",e => e.payload.id == streamid)) {
|
||||||
|
brain.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewSource(btn){
|
||||||
|
let streamid = btn.closest("tr").attr("data-declare");
|
||||||
|
/**
|
||||||
|
* @type {MediaStream}
|
||||||
|
*/
|
||||||
|
let p = null;
|
||||||
|
for (const rawstream of FilterCell("rawstream",e => e.payload.id == streamid)) {
|
||||||
|
p = rawstream.payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
let modal = new ViewSourceDialog(p.getTracks()[0]);
|
||||||
|
modal.enableDialog(this);
|
||||||
|
modal.bringToFront();
|
||||||
|
}
|
||||||
|
generateDevice(){
|
||||||
|
let modal = new AddDeviceDialog();
|
||||||
|
modal.enableDialog(this);
|
||||||
|
modal.bringToFront();
|
||||||
|
modal.addEventListener("stream:added",()=>{
|
||||||
|
this.updateDevices();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StreamRecord extends EventTarget {
|
||||||
|
lockedby = 0;
|
||||||
|
stop(){
|
||||||
|
this.payload.getTracks().forEach(e => e.stop());
|
||||||
|
this.dispatchEvent(new Event("stop"));
|
||||||
|
}
|
||||||
|
isLocked(){
|
||||||
|
return this.lockedby != 0;
|
||||||
|
}
|
||||||
|
lock(){
|
||||||
|
this.lockedby++;
|
||||||
|
}
|
||||||
|
unlock(){
|
||||||
|
this.lockedby--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AddDeviceDialog extends DWindow {
|
||||||
|
constructor(){
|
||||||
|
super();
|
||||||
|
this.initContent();
|
||||||
|
this.headtext.text("Aygıt Ekleme Sihirbazı");
|
||||||
|
this.addEventListener('close',()=>{
|
||||||
|
this.disableDialog();
|
||||||
|
this.exit();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
initContent(){
|
||||||
|
let table = $(`
|
||||||
|
<div style="display:flex;flex-direction:column;gap:5px">
|
||||||
|
<button class="btn btn-success w-100 action-sdcam">
|
||||||
|
SD Kamara Ekle
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn btn-success w-100 action-hdcam">
|
||||||
|
HD Kamara Ekle
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn btn-success w-100 action-mic">
|
||||||
|
Mikrofon Ekle
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn btn-success w-100 action-displaycam">
|
||||||
|
Ekran Görüntüsü Ekle
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
|
||||||
|
table.find(".action-sdcam").on("click",this.sdcam.bind(this));
|
||||||
|
table.find(".action-hdcam").on("click",this.hdcam.bind(this));
|
||||||
|
table.find(".action-mic").on("click",this.mic.bind(this));
|
||||||
|
table.find(".action-displaycam").on("click",this.displaycam.bind(this));
|
||||||
|
this.content.append(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
async sdcam(){
|
||||||
|
let stream = await navigator.mediaDevices.getUserMedia({
|
||||||
|
video: {
|
||||||
|
advanced: [
|
||||||
|
{ width: { exact: 640 } },
|
||||||
|
{ width: { exact: 320 } },
|
||||||
|
{ width: { exact: 240 } }
|
||||||
|
],
|
||||||
|
facingMode: "user"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AddCell("rawstream", new class extends StreamRecord {
|
||||||
|
source = "Kamera";
|
||||||
|
kind = "Görüntü";
|
||||||
|
payload = stream;
|
||||||
|
constructor(){
|
||||||
|
super();
|
||||||
|
this.onEnded(() => {
|
||||||
|
this.dispatchEvent(new Event("stop"));
|
||||||
|
})
|
||||||
|
this.addEventListener("stop",() => {
|
||||||
|
RemoveCell("rawstream",cell => {
|
||||||
|
return cell.payload.id == stream.id
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onEnded(event){
|
||||||
|
/** @type {MediaStreamTrack} */
|
||||||
|
let track;
|
||||||
|
stream.getVideoTracks().forEach(e => track = e);
|
||||||
|
if(track)
|
||||||
|
{
|
||||||
|
track.addEventListener("ended",event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.dispatchEvent(new Event("stream:added"));
|
||||||
|
this.disableDialog();
|
||||||
|
this.exit();
|
||||||
|
}
|
||||||
|
async hdcam(){
|
||||||
|
let stream = await navigator.mediaDevices.getUserMedia({
|
||||||
|
video: {
|
||||||
|
advanced: [
|
||||||
|
{ width: { exact: 1920 } },
|
||||||
|
{ width: { exact: 1600 } },
|
||||||
|
{ width: { exact: 1366 } },
|
||||||
|
{ width: { exact: 1280 } },
|
||||||
|
{ width: { exact: 1024 } },
|
||||||
|
{ width: { exact: 900 } },
|
||||||
|
{ width: { exact: 800 } },
|
||||||
|
{ width: { exact: 640 } },
|
||||||
|
{ width: { exact: 320 } },
|
||||||
|
{ width: { exact: 240 } }
|
||||||
|
],
|
||||||
|
facingMode: "user"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
AddCell("rawstream", new class extends StreamRecord {
|
||||||
|
source = "Kamera";
|
||||||
|
kind = "Görüntü";
|
||||||
|
payload = stream;
|
||||||
|
constructor(){
|
||||||
|
super();
|
||||||
|
this.onEnded(() => {
|
||||||
|
this.dispatchEvent(new Event("stop"));
|
||||||
|
})
|
||||||
|
this.addEventListener("stop",() => {
|
||||||
|
RemoveCell("rawstream",cell => {
|
||||||
|
return cell.payload.id == stream.id
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onEnded(event){
|
||||||
|
/** @type {MediaStreamTrack} */
|
||||||
|
let track;
|
||||||
|
stream.getVideoTracks().forEach(e => track = e);
|
||||||
|
if(track)
|
||||||
|
{
|
||||||
|
track.addEventListener("ended",event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.dispatchEvent(new Event("stream:added"));
|
||||||
|
this.disableDialog();
|
||||||
|
this.exit();
|
||||||
|
}
|
||||||
|
async mic(){
|
||||||
|
let stream = await navigator.mediaDevices.getUserMedia({
|
||||||
|
audio: true
|
||||||
|
});
|
||||||
|
AddCell("rawstream", new class extends StreamRecord {
|
||||||
|
source = "Kamera";
|
||||||
|
kind = "Ses";
|
||||||
|
payload = stream;
|
||||||
|
constructor(){
|
||||||
|
super();
|
||||||
|
this.onEnded(() => {
|
||||||
|
this.dispatchEvent(new Event("stop"));
|
||||||
|
})
|
||||||
|
this.addEventListener("stop",() => {
|
||||||
|
RemoveCell("rawstream",cell => {
|
||||||
|
return cell.payload.id == stream.id
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onEnded(event){
|
||||||
|
/** @type {MediaStreamTrack} */
|
||||||
|
let track;
|
||||||
|
stream.getAudioTracks().forEach(e => track = e);
|
||||||
|
if(track)
|
||||||
|
{
|
||||||
|
track.addEventListener("ended",event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.dispatchEvent(new Event("stream:added"));
|
||||||
|
this.disableDialog();
|
||||||
|
this.exit();
|
||||||
|
}
|
||||||
|
async displaycam(){
|
||||||
|
let stream = await navigator.mediaDevices.getDisplayMedia({
|
||||||
|
video: true
|
||||||
|
});
|
||||||
|
AddCell("rawstream", new class extends StreamRecord{
|
||||||
|
source = "Ekran";
|
||||||
|
kind = "Görüntü";
|
||||||
|
payload = stream;
|
||||||
|
constructor(){
|
||||||
|
super();
|
||||||
|
this.onEnded(() => {
|
||||||
|
this.dispatchEvent(new Event("stop"));
|
||||||
|
})
|
||||||
|
this.addEventListener("stop",() => {
|
||||||
|
RemoveCell("rawstream",cell => {
|
||||||
|
return cell.payload.id == stream.id
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onEnded(event){
|
||||||
|
/** @type {MediaStreamTrack} */
|
||||||
|
let track;
|
||||||
|
stream.getTracks().forEach(e => track = e);
|
||||||
|
if(track)
|
||||||
|
{
|
||||||
|
track.addEventListener("ended",event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.dispatchEvent(new Event("stream:added"));
|
||||||
|
this.disableDialog();
|
||||||
|
this.exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class ViewSourceDialog extends DWindow {
|
||||||
|
/**
|
||||||
|
* @type {MediaStreamTrack}
|
||||||
|
*/
|
||||||
|
track = null;
|
||||||
|
extra = {};
|
||||||
|
constructor(track){
|
||||||
|
super();
|
||||||
|
this.headtext.text("Giriş Kaynağı Görüntüleme");
|
||||||
|
this.addEventListener('close',()=>{
|
||||||
|
this.disableDialog();
|
||||||
|
this.exit();
|
||||||
|
})
|
||||||
|
this.track = track;
|
||||||
|
this.initContent();
|
||||||
|
}
|
||||||
|
initContent(){
|
||||||
|
if(this.track.kind == "video")
|
||||||
|
{
|
||||||
|
this.initVideoContent();
|
||||||
|
}else{
|
||||||
|
this.initAudioContent();
|
||||||
|
}
|
||||||
|
this.table = $(`<table class="table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Track ID</td>
|
||||||
|
<td>${this.track.id}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Data Type</td>
|
||||||
|
<td>${this.track.kind}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Status</td>
|
||||||
|
<td>${this.track.enabled ? "Active" : "Passive"}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Track Label</td>
|
||||||
|
<td>${this.track.label}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>`);
|
||||||
|
this.content.append(this.table);
|
||||||
|
}
|
||||||
|
initVideoContent(){
|
||||||
|
let player = $(`<video
|
||||||
|
style="height: 450px"
|
||||||
|
controls
|
||||||
|
/>`);
|
||||||
|
let stream = new MediaStream();
|
||||||
|
stream.addTrack(this.track);
|
||||||
|
player.on('canplay', e => e.target.play());
|
||||||
|
player.get(0).srcObject = stream;
|
||||||
|
this.content.append(player);
|
||||||
|
player.on('play', e => {
|
||||||
|
this.table.find("tbody").append(`
|
||||||
|
<tr>
|
||||||
|
<td>Video Width</td>
|
||||||
|
<td>${e.target.videoWidth}px</td>
|
||||||
|
</tr>
|
||||||
|
`);
|
||||||
|
this.table.find("tbody").append(`
|
||||||
|
<tr>
|
||||||
|
<td>Video Height</td>
|
||||||
|
<td>${e.target.videoHeight}px</td>
|
||||||
|
</tr>
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
initAudioContent(){
|
||||||
|
let player = $(`<audio
|
||||||
|
style="width: 500px"
|
||||||
|
controls
|
||||||
|
/>`);
|
||||||
|
let stream = new MediaStream();
|
||||||
|
stream.addTrack(this.track);
|
||||||
|
player.get(0).srcObject = stream;
|
||||||
|
player.on('canplay', e => e.target.play());
|
||||||
|
this.content.append(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
import DWindow from "./window.js";
|
||||||
|
import { AddCell, FilterCell, memory, RemoveCell } from "./sdb.js";
|
||||||
|
|
||||||
|
export const Rooms = new class Rooms extends DWindow{
|
||||||
|
constructor(){
|
||||||
|
super();
|
||||||
|
this.emptyConnect();
|
||||||
|
this.headtext.text("MWSE Ağları");
|
||||||
|
this.hide();
|
||||||
|
this.panel.css("min-width","640px");
|
||||||
|
this.addEventListener("close",()=>{
|
||||||
|
this.hide();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
emptyConnect(){
|
||||||
|
this.content.append($(`
|
||||||
|
<h4 class="text-white text-center">MWSE Ağları</h4>
|
||||||
|
`),$(`
|
||||||
|
<h6 class="text-white text-center">Herhangi bir ağa bağlı değilsiniz</h6>
|
||||||
|
`));
|
||||||
|
|
||||||
|
|
||||||
|
this.content.append($(`
|
||||||
|
<h3 class="text-white text-center" style="margin-top: 50px">
|
||||||
|
Ağ Oluştur
|
||||||
|
</h3>
|
||||||
|
`));
|
||||||
|
|
||||||
|
let createinput = $(`
|
||||||
|
<input type="text" class="form-control" placeholder="Oluşturulacak Oda Adı" style="line-height:2;font-size: 2em">
|
||||||
|
`);
|
||||||
|
|
||||||
|
let createbutton = $(`
|
||||||
|
<button class="btn btn-lg btn-success d-block m-auto mt-3">Oluştur</button>
|
||||||
|
`);
|
||||||
|
|
||||||
|
this.content.append(createinput,createbutton);
|
||||||
|
|
||||||
|
this.content.append($(`
|
||||||
|
<h3 class="text-white text-center" style="margin-top: 50px">
|
||||||
|
Ağa Katıl
|
||||||
|
</h3>
|
||||||
|
`));
|
||||||
|
|
||||||
|
let joininput = $(`
|
||||||
|
<input type="text" class="form-control" placeholder="Katılacak Oda Adı" style="line-height:2;font-size: 2em">
|
||||||
|
`);
|
||||||
|
|
||||||
|
|
||||||
|
let joinbutton = $(`
|
||||||
|
<button class="btn btn-lg btn-success d-block m-auto mt-3">Katıl</button>
|
||||||
|
`);
|
||||||
|
this.content.append(joininput,joinbutton);
|
||||||
|
|
||||||
|
this.content.append($(`
|
||||||
|
<span class="text-white" style="margin-top: 50px;max-width:100%;font-size: 0.9em;line-height: 1;display: block;text-shadow: 0px 0px 4px black;">
|
||||||
|
Aynı ağdaki kullanıcılar birbirini görecek ve akışlarını paylaşabilecektir.
|
||||||
|
Verilerinizi, bilgilerinizi ve akışlarınızı paylaşmakta tamamen özgürsünüz.
|
||||||
|
Sistem tamamen deneysel teknoloji araştırma ve geliştirme üzerine kuruludur.
|
||||||
|
Sistem kullanılarak yapılan tüm iyi ve kötü amaçlı eylemlerden kullanıcı sorumludur.
|
||||||
|
</span>
|
||||||
|
`));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 660 KiB |
|
|
@ -0,0 +1,162 @@
|
||||||
|
const style = document.createElement("style");
|
||||||
|
document.head.appendChild(style);
|
||||||
|
|
||||||
|
export default class CSSOM {
|
||||||
|
/** @type {Map<string, CSSOM>} */
|
||||||
|
static rules = new Map();
|
||||||
|
/** @type {Map<string, CSSRuleList>} */
|
||||||
|
static cRules = new Map();
|
||||||
|
/**
|
||||||
|
* @returns {CSSOM}
|
||||||
|
*/
|
||||||
|
static get(name){
|
||||||
|
return CSSOM.rules.get(name);
|
||||||
|
}
|
||||||
|
/** @returns {CSSRule} */
|
||||||
|
static findRule(selector){
|
||||||
|
for (let ruleIndex = 0; ruleIndex < style.sheet.cssRules.length; ruleIndex++)
|
||||||
|
{
|
||||||
|
let rule = style.sheet.cssRules.item(ruleIndex);
|
||||||
|
if(rule.selectorText == selector)
|
||||||
|
{
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** @returns {CSSRule} */
|
||||||
|
static removeRule(selector){
|
||||||
|
for (let ruleIndex = 0; ruleIndex < style.sheet.cssRules.length; ruleIndex++)
|
||||||
|
{
|
||||||
|
let rule = style.sheet.cssRules.item(ruleIndex);
|
||||||
|
if(rule.selectorText == selector)
|
||||||
|
{
|
||||||
|
style.sheet.deleteRule(ruleIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static css(selector, values){
|
||||||
|
let rule;
|
||||||
|
if(!(rule = CSSOM.findRule(selector)))
|
||||||
|
{
|
||||||
|
let no = style.sheet.insertRule(`${selector}{}`);
|
||||||
|
rule = style.sheet.cssRules[no];
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let [stylename, stylevalue] of Object.entries(values))
|
||||||
|
{
|
||||||
|
let name = stylename;
|
||||||
|
let value = typeof stylevalue == "string" ? stylevalue.split('!')[0] : stylevalue;
|
||||||
|
let priority = typeof stylevalue == "string" ? (stylevalue.split('!')[1] == "important" ? "important" : void 0) : void 0;
|
||||||
|
|
||||||
|
|
||||||
|
name = name.replace(/([A-Z])/g,(_,$1) => '-' + $1.toLowerCase());
|
||||||
|
|
||||||
|
rule.style.setProperty(name, value, priority);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static generate(idd = null, css = null){
|
||||||
|
let id = idd || CSSOM.generateCode();
|
||||||
|
let t = new CSSOM(id);
|
||||||
|
CSSOM.rules.set(t.id,t);
|
||||||
|
css && t.css(css);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
static generateCode(){
|
||||||
|
let mine;
|
||||||
|
do{
|
||||||
|
mine = Math.random().toString(36).slice(2,6);
|
||||||
|
}while(CSSOM.rules.has(mine));
|
||||||
|
return "i" + mine;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = "";
|
||||||
|
/** @type {{[key:string]: CSSRuleList}} */
|
||||||
|
rule_t = {};
|
||||||
|
constructor(id){
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
toString(){
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
css(name, value, prefix = 'owner'){
|
||||||
|
let rule;
|
||||||
|
if(!this.rule_t[prefix])
|
||||||
|
{
|
||||||
|
let rulename = `.${this.id}` + (prefix == "owner" ? "" : prefix);
|
||||||
|
let no = style.sheet.insertRule(`${rulename}{}`);
|
||||||
|
this.rule_t[prefix] = style.sheet.cssRules[no];
|
||||||
|
};
|
||||||
|
rule = this.rule_t[prefix];
|
||||||
|
if(value === undefined && typeof name == "string")
|
||||||
|
{
|
||||||
|
return rule.style.getPropertyValue(name);
|
||||||
|
}
|
||||||
|
if(value === null)
|
||||||
|
{
|
||||||
|
rule.style.removeProperty(name, value);
|
||||||
|
}else{
|
||||||
|
if(typeof name == "object")
|
||||||
|
{
|
||||||
|
for(let [stylename, stylevalue] of Object.entries(name))
|
||||||
|
{
|
||||||
|
let name = stylename;
|
||||||
|
let value = typeof stylevalue == "string" ? stylevalue.split('!')[0] : stylevalue;
|
||||||
|
let priority = typeof stylevalue == "string" ? (stylevalue.split('!')[1] == "important" ? "!important" : void 0) : stylevalue;
|
||||||
|
if(name.indexOf('-') == -1)
|
||||||
|
{
|
||||||
|
rule.style[name] = value + (priority || "");
|
||||||
|
}else{
|
||||||
|
rule.style.setProperty(name, value, priority);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
rule.style.setProperty(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.cssom = function(obj, prefix){
|
||||||
|
if(prefix === void 0 || (typeof obj == "object" && typeof prefix == "string"))
|
||||||
|
{
|
||||||
|
let cssom;
|
||||||
|
if(this.attr("data-cssom"))
|
||||||
|
{
|
||||||
|
let name = this.attr("data-cssom");
|
||||||
|
cssom = CSSOM.get(name)
|
||||||
|
}else{
|
||||||
|
cssom = CSSOM.generate();
|
||||||
|
this.addClass(cssom.id);
|
||||||
|
this.attr("data-cssom", cssom.id);
|
||||||
|
}
|
||||||
|
cssom.css(obj,void 0,prefix);
|
||||||
|
}else{
|
||||||
|
|
||||||
|
if(obj.indexOf(":") == -1){
|
||||||
|
this.addClass(obj);
|
||||||
|
CSSOM.css("." + obj, prefix);
|
||||||
|
}else{
|
||||||
|
|
||||||
|
let [_class,_psudio] = obj.split(":");
|
||||||
|
|
||||||
|
this.addClass(_class);
|
||||||
|
CSSOM.css("." + _class + ":" + _psudio, prefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
window.debugCssom = function(){
|
||||||
|
for (let ruleIndex = 0; ruleIndex < style.sheet.cssRules.length; ruleIndex++)
|
||||||
|
{
|
||||||
|
let rule = style.sheet.cssRules.item(ruleIndex);
|
||||||
|
console.log(rule.cssText)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.cssom = CSSOM;
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
* @ typedef {Object} BirthData
|
||||||
|
* @ property {Date} birthDate
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @typedef {Object} BrainCell
|
||||||
|
* @property {string} type
|
||||||
|
* @property {Object} data
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @type {BrainCell[]}
|
||||||
|
*/
|
||||||
|
export let memory = [];
|
||||||
|
|
||||||
|
export function AddCell(name, data)
|
||||||
|
{
|
||||||
|
memory.push({
|
||||||
|
type: name,
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @param {string} type
|
||||||
|
* @param {(BrainCell) => boolean} filterQuery
|
||||||
|
*/
|
||||||
|
export function RemoveCell(type, filterQuery)
|
||||||
|
{
|
||||||
|
memory = memory.filter(e => !(
|
||||||
|
e.type == type && filterQuery(e.data)
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} type
|
||||||
|
* @param {(BrainCell) => boolean} filterQuery
|
||||||
|
*/
|
||||||
|
export function FilterCell(type, filterQuery)
|
||||||
|
{
|
||||||
|
return memory.filter(e =>
|
||||||
|
e.type == type && filterQuery(e.data)
|
||||||
|
).map(e => e.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.memoryDump = () => memory;
|
||||||
|
|
@ -0,0 +1,293 @@
|
||||||
|
export default class DWindow extends EventTarget {
|
||||||
|
static allWindows = []; // açık pencereler
|
||||||
|
static zCounter = 1; // global sayaç
|
||||||
|
static normalizeThreshold = 9999; // yeniden sıfırlama eşiği
|
||||||
|
/** @type {JQuery<HTMLElement>} */ panel = null;
|
||||||
|
/** @type {JQuery<HTMLElement>} */ title = null;
|
||||||
|
/** @type {JQuery<HTMLElement>} */ content = null;
|
||||||
|
/** @type {JQuery<HTMLElement>} */ headtext = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.initpanel();
|
||||||
|
this.enableFocus();
|
||||||
|
DWindow.allWindows.push(this);
|
||||||
|
this.bringToFront();
|
||||||
|
requestAnimationFrame(()=>{
|
||||||
|
this.enableDragging();
|
||||||
|
this.enableResize();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
activeDragging = true;
|
||||||
|
activeResizing = true;
|
||||||
|
|
||||||
|
initpanel() {
|
||||||
|
this.panel = $(`<div></div>`).css({
|
||||||
|
width: 450,
|
||||||
|
//height: 500,
|
||||||
|
position: "fixed",
|
||||||
|
left: (Math.random() * 300 | 0) + 100,
|
||||||
|
top: (Math.random() * 100 | 0) + 100,
|
||||||
|
boxShadow: "black 0px 0px 20px -10px",
|
||||||
|
borderRadius: "10px",
|
||||||
|
backgroundColor: "#3333335b",
|
||||||
|
backdropFilter: "blur(3px)",
|
||||||
|
border: "solid 1px #a2a2a2",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
outlineOffset: "-5px",
|
||||||
|
//overflow: "hidden",
|
||||||
|
userSelect: "none",
|
||||||
|
minWidth: "max-content",
|
||||||
|
minHeight: "max-content"
|
||||||
|
});
|
||||||
|
$("body").append(this.panel);
|
||||||
|
|
||||||
|
this.title = $(`<div></div>`).css({
|
||||||
|
display: "flex",
|
||||||
|
flex: "0 0 auto",
|
||||||
|
flexDirection: "row",
|
||||||
|
lineHeight: "2em",
|
||||||
|
backgroundColor: "#333333",
|
||||||
|
color: "white",
|
||||||
|
paddingLeft: "10px",
|
||||||
|
cursor: "move",
|
||||||
|
borderTopLeftRadius: "10px",
|
||||||
|
borderTopRightRadius: "10px",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.content = $(`<div></div>`).css({
|
||||||
|
flex: "1 1 auto",
|
||||||
|
overflow: "auto",
|
||||||
|
borderBottomRightRadius: "10px",
|
||||||
|
borderBottomLeftRadius: "10px",
|
||||||
|
padding: "20px"
|
||||||
|
});
|
||||||
|
|
||||||
|
this.panel.append(this.title, this.content);
|
||||||
|
this.initTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
initTitle() {
|
||||||
|
this.headtext = $("<div>Başlıksız pencere</div>");
|
||||||
|
const divider = $("<div style='flex:1 1 auto'></div>");
|
||||||
|
this.exitbtn = $("<div><span class='btn btn-sm material-symbols-outlined text-white'>close</span></div>");
|
||||||
|
this.exitbtn.on('click',()=>{
|
||||||
|
this.dispatchEvent(new Event("close"));
|
||||||
|
})
|
||||||
|
this.title.append(
|
||||||
|
this.headtext,
|
||||||
|
divider,
|
||||||
|
this.exitbtn
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
enableDragging() {
|
||||||
|
let isDragging = false;
|
||||||
|
let startX, startY, startLeft, startTop;
|
||||||
|
|
||||||
|
this.title.on("mousedown", (e) => {
|
||||||
|
if(this.activeDragging == false){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let isInput = $(e.target).closest("button, input, select, textarea,.btn");
|
||||||
|
if (isInput.length) return;
|
||||||
|
e.preventDefault();
|
||||||
|
isDragging = true;
|
||||||
|
startX = e.pageX;
|
||||||
|
startY = e.pageY;
|
||||||
|
startLeft = parseFloat(this.panel.css("left"));
|
||||||
|
startTop = parseFloat(this.panel.css("top"));
|
||||||
|
$("body").css("user-select", "none");
|
||||||
|
this.dispatchEvent(new Event("dragging"));
|
||||||
|
this.panel.css("box-shadow","black 0px 0px 40px -20px");
|
||||||
|
this.panel.css("backdrop-filter","blur(10px)");
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on("mousemove", (e) => {
|
||||||
|
if (!isDragging) return;
|
||||||
|
const dx = e.pageX - startX;
|
||||||
|
const dy = e.pageY - startY;
|
||||||
|
|
||||||
|
this.panel.css({
|
||||||
|
left: startLeft + dx,
|
||||||
|
top: startTop + dy,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on("mouseup", () => {
|
||||||
|
if (isDragging) {
|
||||||
|
isDragging = false;
|
||||||
|
this.panel.css("box-shadow","black 0px 0px 20px -10px");
|
||||||
|
this.panel.css("backdrop-filter","blur(3px)");
|
||||||
|
$("body").css("user-select", "auto");
|
||||||
|
this.dispatchEvent(new Event("draggingend"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
enableResize() {
|
||||||
|
const offset = 5; // panelin dışından 5px alan
|
||||||
|
let resizing = false;
|
||||||
|
let resizeDir = "";
|
||||||
|
let startX, startY, startW, startH, startL, startT;
|
||||||
|
const minW = 200, minH = 150;
|
||||||
|
|
||||||
|
// overlay divleri oluştur
|
||||||
|
const handles = {};
|
||||||
|
const names = ["n","s","e","w","ne","nw","se","sw"];
|
||||||
|
names.forEach(n => {
|
||||||
|
handles[n] = $('<div></div>').css({
|
||||||
|
position: "absolute",
|
||||||
|
zIndex: 1000,
|
||||||
|
background: "transparent",
|
||||||
|
cursor: n + "-resize",
|
||||||
|
transition: "all 0.5s all",
|
||||||
|
outlineOffset: "3px"
|
||||||
|
}).appendTo(this.panel);
|
||||||
|
});
|
||||||
|
|
||||||
|
// boyut ve pozisyonlarını ayarla
|
||||||
|
const updateHandles = () => {
|
||||||
|
const w = this.panel.outerWidth();
|
||||||
|
const h = this.panel.outerHeight();
|
||||||
|
// kenarlar
|
||||||
|
handles.n.css({ top: -offset, left: 0, width: w, height: offset*2 });
|
||||||
|
handles.s.css({ bottom: -offset, left: 0, width: w, height: offset*2 });
|
||||||
|
handles.w.css({ top: 0, left: -offset, width: offset*2, height: h });
|
||||||
|
handles.e.css({ top: 0, right: -offset, width: offset*2, height: h });
|
||||||
|
// köşeler
|
||||||
|
handles.nw.css({ top: -offset, left: -offset, width: offset*2, height: offset*2 });
|
||||||
|
handles.ne.css({ top: -offset, right: -offset, width: offset*2, height: offset*2 });
|
||||||
|
handles.sw.css({ bottom: -offset, left: -offset, width: offset*2, height: offset*2 });
|
||||||
|
handles.se.css({ bottom: -offset, right: -offset, width: offset*2, height: offset*2 });
|
||||||
|
};
|
||||||
|
updateHandles();
|
||||||
|
|
||||||
|
$(window).on("resize", updateHandles);
|
||||||
|
|
||||||
|
let activeDir = null;
|
||||||
|
|
||||||
|
// resize eventleri
|
||||||
|
names.forEach(dir => {
|
||||||
|
handles[dir].on("mousedown", (e) => {
|
||||||
|
if(this.activeResizing == false){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
activeDir = e.target;
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
resizing = true;
|
||||||
|
resizeDir = dir;
|
||||||
|
startX = e.pageX;
|
||||||
|
startY = e.pageY;
|
||||||
|
startW = this.panel.outerWidth();
|
||||||
|
startH = this.panel.outerHeight();
|
||||||
|
startL = parseFloat(this.panel.css("left"));
|
||||||
|
startT = parseFloat(this.panel.css("top"));
|
||||||
|
this.dispatchEvent(new Event("resizing"));
|
||||||
|
$("body").css("user-select","none");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on("mousemove", (e) => {
|
||||||
|
if (!resizing) return;
|
||||||
|
const dx = e.pageX - startX;
|
||||||
|
const dy = e.pageY - startY;
|
||||||
|
let newW = startW;
|
||||||
|
let newH = startH;
|
||||||
|
let newL = startL;
|
||||||
|
let newT = startT;
|
||||||
|
|
||||||
|
if (resizeDir.includes("e")) newW = Math.max(minW, startW + dx);
|
||||||
|
if (resizeDir.includes("w")) { newW = Math.max(minW, startW - dx); newL = startL + (startW - newW); }
|
||||||
|
if (resizeDir.includes("s")) newH = Math.max(minH, startH + dy);
|
||||||
|
if (resizeDir.includes("n")) { newH = Math.max(minH, startH - dy); newT = startT + (startH - newH); }
|
||||||
|
|
||||||
|
this.panel.css({ width: newW, height: newH, left: newL, top: newT });
|
||||||
|
updateHandles();
|
||||||
|
$(activeDir).css("outline", "solid 2px #00ff00");
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on("mouseup", () => {
|
||||||
|
if (resizing) {
|
||||||
|
resizing = false;
|
||||||
|
$("body").css("user-select","auto");
|
||||||
|
$(activeDir).css("outline", "solid 0px #00ff00");
|
||||||
|
this.dispatchEvent(new Event("resizingend"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
enableFocus() {
|
||||||
|
this.panel.on("mousedown", () => {
|
||||||
|
this.bringToFront();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bringToFront() {
|
||||||
|
if (DWindow.zCounter > DWindow.normalizeThreshold) {
|
||||||
|
DWindow.normalizeZ();
|
||||||
|
}
|
||||||
|
DWindow.zCounter++;
|
||||||
|
this.panel.css("z-index", DWindow.zCounter);
|
||||||
|
}
|
||||||
|
showing = true;
|
||||||
|
show(){
|
||||||
|
this.dispatchEvent(new Event("show"));
|
||||||
|
this.panel.show();
|
||||||
|
this.showing = true;
|
||||||
|
}
|
||||||
|
hide(){
|
||||||
|
this.dispatchEvent(new Event("hide"));
|
||||||
|
this.panel.hide();
|
||||||
|
this.showing = false;
|
||||||
|
}
|
||||||
|
toggle(){
|
||||||
|
this.showing ? this.hide() : this.show();
|
||||||
|
}
|
||||||
|
exit(){
|
||||||
|
this.dispatchEvent(new Event("exit"));
|
||||||
|
this.panel.remove();
|
||||||
|
}
|
||||||
|
/** @type {DWindow} */
|
||||||
|
parent = null;
|
||||||
|
/** @param {DWindow} parent */
|
||||||
|
enableDialog(parent){
|
||||||
|
this.parent = parent;
|
||||||
|
this.parent.activeDragging = false;
|
||||||
|
this.parent.activeResizing = false;
|
||||||
|
this.parent.panel.css('pointer-events',"none");
|
||||||
|
this.parent.panel.css('filter',"grayscale(1)");
|
||||||
|
|
||||||
|
let [{
|
||||||
|
left: parentL,
|
||||||
|
top: parentT,
|
||||||
|
width: parentW,
|
||||||
|
height: parentH
|
||||||
|
}] = this.parent.panel[0].getClientRects();
|
||||||
|
|
||||||
|
let [{
|
||||||
|
width: childW,
|
||||||
|
height: childH
|
||||||
|
}] = this.panel[0].getClientRects();
|
||||||
|
|
||||||
|
let newLeft = parentL + (parentW - childW) / 2;
|
||||||
|
let newTop = parentT + (parentH - childH) / 2;
|
||||||
|
debugger;
|
||||||
|
newLeft = Math.max(newLeft, 20);
|
||||||
|
newTop = Math.max(newTop, 20);
|
||||||
|
newLeft = Math.min(newLeft, screen.availWidth - 100);
|
||||||
|
newTop = Math.min(newTop, screen.availHeight - 100);
|
||||||
|
|
||||||
|
Object.assign(this.panel[0].style, {
|
||||||
|
left: `${Math.round(newLeft)}px`,
|
||||||
|
top: `${Math.round(newTop)}px`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/** @param {DWindow} parent */
|
||||||
|
disableDialog(){
|
||||||
|
this.parent.activeDragging = true;
|
||||||
|
this.parent.activeResizing = true;
|
||||||
|
this.parent.panel.css('pointer-events',"all");
|
||||||
|
this.parent.panel.css('filter',"initial");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,9 +12,9 @@ async function beginEngine()
|
||||||
accessType: "private",
|
accessType: "private",
|
||||||
description: "Private free joined room",
|
description: "Private free joined room",
|
||||||
ifexistsJoin: false,
|
ifexistsJoin: false,
|
||||||
notifyActionEjected: true,
|
notifyActionEjected: false,
|
||||||
notifyActionInvite: false,
|
notifyActionInvite: false,
|
||||||
notifyActionJoined: true
|
notifyActionJoined: false
|
||||||
});
|
});
|
||||||
try{
|
try{
|
||||||
await room.createRoom();
|
await room.createRoom();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,166 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="tr">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
|
<title>jQuery ile Resizable Kutu</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: Arial, Helvetica, sans-serif; height:100vh; margin:0; display:flex; align-items:center; justify-content:center; background:#f2f2f2; }
|
||||||
|
.stage { width:90vw; height:80vh; border:1px solid #ccc; position:relative; background:#fff; }
|
||||||
|
.box {
|
||||||
|
position:absolute;
|
||||||
|
left:50px; top:50px;
|
||||||
|
width:300px; height:200px;
|
||||||
|
background:#e8f0ff;
|
||||||
|
border:1px solid #5b8cff;
|
||||||
|
box-sizing:border-box;
|
||||||
|
user-select:none;
|
||||||
|
}
|
||||||
|
/* küçücük tutamaklar (handles) */
|
||||||
|
.handle {
|
||||||
|
position:absolute;
|
||||||
|
width:12px; height:12px;
|
||||||
|
background:#5b8cff;
|
||||||
|
border-radius:2px;
|
||||||
|
margin:-6px 0 0 -6px; /* merkezler */
|
||||||
|
cursor:default;
|
||||||
|
}
|
||||||
|
.handle.n { top:0; left:50%; cursor:n-resize; }
|
||||||
|
.handle.s { bottom:0; left:50%; cursor:s-resize; }
|
||||||
|
.handle.e { right:0; top:50%; cursor:e-resize; }
|
||||||
|
.handle.w { left:0; top:50%; cursor:w-resize; }
|
||||||
|
.handle.ne { right:0; top:0; cursor:ne-resize; }
|
||||||
|
.handle.nw { left:0; top:0; cursor:nw-resize; }
|
||||||
|
.handle.se { right:0; bottom:0; cursor:se-resize; }
|
||||||
|
.handle.sw { left:0; bottom:0; cursor:sw-resize; }
|
||||||
|
/* bilgi satırı (isteğe bağlı) */
|
||||||
|
.info { position:absolute; left:6px; bottom:6px; font-size:12px; color:#333; background:rgba(255,255,255,0.8); padding:4px 6px; border-radius:4px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="stage">
|
||||||
|
<div class="box" id="resizable">
|
||||||
|
<div class="handle n" data-dir="n"></div>
|
||||||
|
<div class="handle s" data-dir="s"></div>
|
||||||
|
<div class="handle e" data-dir="e"></div>
|
||||||
|
<div class="handle w" data-dir="w"></div>
|
||||||
|
<div class="handle ne" data-dir="ne"></div>
|
||||||
|
<div class="handle nw" data-dir="nw"></div>
|
||||||
|
<div class="handle se" data-dir="se"></div>
|
||||||
|
<div class="handle sw" data-dir="sw"></div>
|
||||||
|
<div class="info" id="info"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
||||||
|
<script>
|
||||||
|
$(function(){
|
||||||
|
var $doc = $(document);
|
||||||
|
var $box = $('#resizable');
|
||||||
|
var dragging = false;
|
||||||
|
var dir = null;
|
||||||
|
var start = {}; // {mouseX, mouseY, left, top, width, height}
|
||||||
|
var minW = 60, minH = 40;
|
||||||
|
|
||||||
|
function updateInfo(){
|
||||||
|
var w = Math.round($box.width()), h = Math.round($box.height());
|
||||||
|
$('#info').text(w + ' x ' + h);
|
||||||
|
}
|
||||||
|
updateInfo();
|
||||||
|
|
||||||
|
$box.on('mousedown', '.handle', function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
dragging = true;
|
||||||
|
dir = $(this).data('dir');
|
||||||
|
var offset = $box.position();
|
||||||
|
start = {
|
||||||
|
mouseX: e.pageX,
|
||||||
|
mouseY: e.pageY,
|
||||||
|
left: offset.left,
|
||||||
|
top: offset.top,
|
||||||
|
width: $box.outerWidth(),
|
||||||
|
height: $box.outerHeight()
|
||||||
|
};
|
||||||
|
// disable text selection while dragging
|
||||||
|
$('body').css('user-select','none');
|
||||||
|
});
|
||||||
|
|
||||||
|
$doc.on('mousemove', function(e){
|
||||||
|
if(!dragging) return;
|
||||||
|
e.preventDefault();
|
||||||
|
var dx = e.pageX - start.mouseX;
|
||||||
|
var dy = e.pageY - start.mouseY;
|
||||||
|
var newLeft = start.left;
|
||||||
|
var newTop = start.top;
|
||||||
|
var newW = start.width;
|
||||||
|
var newH = start.height;
|
||||||
|
|
||||||
|
// handle horizontal changes
|
||||||
|
if(dir.indexOf('e') !== -1){
|
||||||
|
newW = Math.max(minW, start.width + dx);
|
||||||
|
}
|
||||||
|
if(dir.indexOf('w') !== -1){
|
||||||
|
newW = Math.max(minW, start.width - dx);
|
||||||
|
newLeft = start.left + (start.width - newW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle vertical changes
|
||||||
|
if(dir.indexOf('s') !== -1){
|
||||||
|
newH = Math.max(minH, start.height + dy);
|
||||||
|
}
|
||||||
|
if(dir.indexOf('n') !== -1){
|
||||||
|
newH = Math.max(minH, start.height - dy);
|
||||||
|
newTop = start.top + (start.height - newH);
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply
|
||||||
|
$box.css({ left: newLeft + 'px', top: newTop + 'px', width: newW + 'px', height: newH + 'px' });
|
||||||
|
updateInfo();
|
||||||
|
});
|
||||||
|
|
||||||
|
$doc.on('mouseup mouseleave', function(){
|
||||||
|
if(dragging){
|
||||||
|
dragging = false;
|
||||||
|
dir = null;
|
||||||
|
$('body').css('user-select','auto');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// optional: allow dragging the whole box when clicking inside (but not on handles)
|
||||||
|
var draggingBox = false, dragBoxStart = {};
|
||||||
|
$box.on('mousedown', function(e){
|
||||||
|
if($(e.target).hasClass('handle')) return;
|
||||||
|
e.preventDefault();
|
||||||
|
draggingBox = true;
|
||||||
|
dragBoxStart = { mouseX: e.pageX, mouseY: e.pageY, left: $box.position().left, top: $box.position().top };
|
||||||
|
$('body').css('user-select','none');
|
||||||
|
});
|
||||||
|
$doc.on('mousemove', function(e){
|
||||||
|
if(!draggingBox) return;
|
||||||
|
var nx = dragBoxStart.left + (e.pageX - dragBoxStart.mouseX);
|
||||||
|
var ny = dragBoxStart.top + (e.pageY - dragBoxStart.mouseY);
|
||||||
|
$box.css({ left: nx + 'px', top: ny + 'px' });
|
||||||
|
});
|
||||||
|
$doc.on('mouseup', function(){
|
||||||
|
if(draggingBox){
|
||||||
|
draggingBox = false;
|
||||||
|
$('body').css('user-select','auto');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// keyboard nudges (isteğe bağlı)
|
||||||
|
$doc.on('keydown', function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
if(!e.altKey) return; // alt ile etkinleştir
|
||||||
|
var pos = $box.position();
|
||||||
|
if(e.key === 'ArrowLeft') $box.css('left', pos.left - 1);
|
||||||
|
if(e.key === 'ArrowRight') $box.css('left', pos.left + 1);
|
||||||
|
if(e.key === 'ArrowUp') $box.css('top', pos.top - 1);
|
||||||
|
if(e.key === 'ArrowDown') $box.css('top', pos.top + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue