kdsjdjks
This commit is contained in:
@@ -1,16 +1,33 @@
|
||||
<script setup lang="ts">
|
||||
import WindowManager from './components/managers/WindowManager.vue';
|
||||
import Content from './components/viewer/content/Content.vue';
|
||||
import StatusBar from './components/viewer/statusbar/StatusBar.vue';
|
||||
import TopBar from './components/viewer/TopBar.vue';
|
||||
|
||||
|
||||
import { CreateWindow } from '@/services/Windows'
|
||||
|
||||
async function start(){
|
||||
CreateWindow('login');
|
||||
|
||||
// DisplayToast('aqua', 'All plugins loaded successfully');
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
start();
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="viewer">
|
||||
<WindowManager></WindowManager>
|
||||
|
||||
|
||||
<TopBar></TopBar>
|
||||
<Content></Content>
|
||||
<StatusBar></StatusBar>
|
||||
|
||||
<!-- Managers -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
@use "sass:map";
|
||||
|
||||
$themes: (
|
||||
dark: (
|
||||
background: #141414,
|
||||
background-line: #202324,
|
||||
background-fore: #10141f,
|
||||
hover: #21262d,
|
||||
selected: #4a4a4b,
|
||||
border-color: #819796,
|
||||
border: #202324,
|
||||
text: #ebede9,
|
||||
container-shadow: #151d28,
|
||||
sticky-header-bg: #20202077
|
||||
),
|
||||
light: (
|
||||
background: #ffffff,
|
||||
background-line: #f0f0f0,
|
||||
background-fore: #ffffff,
|
||||
border-color: #e0e0e0,
|
||||
border: #f0f0f0,
|
||||
hover: #e9e9e9,
|
||||
selected: #d4d4d4,
|
||||
text: #1e1e1e,
|
||||
container-shadow: #5f6774,
|
||||
sticky-header-bg: #fff
|
||||
)
|
||||
);
|
||||
|
||||
$accents: (
|
||||
katlum: (
|
||||
link: #a4dddb,
|
||||
),
|
||||
solus: (
|
||||
link: #e6a556,
|
||||
),
|
||||
silang: (
|
||||
link: #c65197,
|
||||
)
|
||||
);
|
||||
|
||||
@mixin theme-vars($theme-map) {
|
||||
@each $name, $value in $theme-map {
|
||||
--color-#{$name}: #{$value};
|
||||
}
|
||||
}
|
||||
|
||||
@mixin accent-vars($accent-map) {
|
||||
@each $name, $value in $accent-map {
|
||||
--color-#{$name}: #{$value};
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
@include theme-vars(map.get($themes, dark));
|
||||
@include accent-vars(map.get($accents, katlum));
|
||||
}
|
||||
|
||||
[data-theme="light"] {
|
||||
@include theme-vars(map.get($themes, light));
|
||||
}
|
||||
|
||||
[data-accent="katlum"] {
|
||||
@include accent-vars(map.get($accents, katlum));
|
||||
}
|
||||
|
||||
[data-accent="solus"] {
|
||||
@include accent-vars(map.get($accents, solus));
|
||||
}
|
||||
|
||||
[data-accent="silang"] {
|
||||
@include accent-vars(map.get($accents, silang));
|
||||
}
|
||||
@@ -37,4 +37,18 @@ a {
|
||||
|
||||
.error-link {
|
||||
color: var(--error-link);
|
||||
}
|
||||
|
||||
|
||||
.window-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: solid 1px var(--color-border);
|
||||
|
||||
/* opacity: 0; */
|
||||
|
||||
user-select: none;
|
||||
-webkit-box-shadow: 0px 0px 10px -2px var(--shadow-color);
|
||||
-moz-box-shadow: 0px 0px 10px -2px var(--shadow-color);
|
||||
box-shadow: 0px 0px 10px -2px var(--shadow-color);
|
||||
}
|
||||
42
frontend/app/components/managers/WindowManager.vue
Normal file
42
frontend/app/components/managers/WindowManager.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<script setup>
|
||||
import { TransitionGroup } from 'vue'
|
||||
import { Windows, ReloadRef, WindowMap } from '@/services/Windows';
|
||||
|
||||
// Gestionem ventanas
|
||||
const reload = ReloadRef();
|
||||
const windows = Windows();
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="window-container" :key="reload">
|
||||
<TransitionGroup name="window">
|
||||
<component v-for="win in windows" :is="WindowMap()[win.type]" :key="win.id" :data="win"></component>
|
||||
</TransitionGroup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style>
|
||||
.window-enter-active,
|
||||
.window-leave-active {
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
.window-enter-from,
|
||||
.window-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(15px);
|
||||
}
|
||||
|
||||
.window-wrapper {
|
||||
background-color: var(--window-background);
|
||||
|
||||
/* backdrop-filter: blur(10px); */
|
||||
position: fixed;
|
||||
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
</style>
|
||||
44
frontend/app/components/windows/LoginWindow.vue
Normal file
44
frontend/app/components/windows/LoginWindow.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { SetupHandle, SetSize, ResetPosition } from '@/services/Windows';
|
||||
|
||||
import WindowHandle from './partials/WindowHandle.vue';
|
||||
|
||||
const handle = ref(null);
|
||||
|
||||
const props = defineProps(['data']);
|
||||
const data = props.data;
|
||||
|
||||
let id = data.id;
|
||||
|
||||
const test = ref(null)
|
||||
|
||||
onMounted(() => {
|
||||
SetupHandle(id, handle);
|
||||
SetSize(id, {width: 500, height: 380});
|
||||
ResetPosition(id, "center");
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="window-wrapper" :id="'window-wrapper-' + id">
|
||||
<WindowHandle :window="id" ref="handle"></WindowHandle>
|
||||
|
||||
<!-- Body -->
|
||||
<div ref="test">
|
||||
<p>Hola</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.window-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
139
frontend/app/components/windows/partials/WindowHandle.vue
Normal file
139
frontend/app/components/windows/partials/WindowHandle.vue
Normal file
@@ -0,0 +1,139 @@
|
||||
<script setup>
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { GetWindowWithId, ClearWindow, Windows } from '@/services/Windows';
|
||||
|
||||
import ArrowLeftIcon from '/icons/iconoir/regular/arrow-left.svg';
|
||||
import XMarkIcon from '/icons/iconoir/regular/xmark.svg';
|
||||
import ResizeHandleIcon from '/icons/ui/resize-handle.svg';
|
||||
|
||||
const props = defineProps(['window', 'handleHeight', 'custom', 'color']);
|
||||
const id = props.window;
|
||||
const handleHeight = props.handleHeight;
|
||||
|
||||
const closeButton = ref(null);
|
||||
const backButton = ref(null);
|
||||
|
||||
const title = ref("");
|
||||
const close = ref(false);
|
||||
const hasBack = ref(false);
|
||||
const def = ref(true);
|
||||
const resizable = ref(false);
|
||||
|
||||
let closeAction;
|
||||
|
||||
let backFunction;
|
||||
|
||||
function setupHandle() {
|
||||
let win = GetWindowWithId(id);
|
||||
if(win.title) title.value = win.title;
|
||||
if(win.close){
|
||||
close.value = true;
|
||||
closeAction = win.close;
|
||||
}
|
||||
if(win.back) {
|
||||
hasBack.value = true;
|
||||
backFunction = win.back;
|
||||
}
|
||||
|
||||
if(handleHeight) {
|
||||
let handle = document.getElementById('window-handle-' + id);
|
||||
handle.style.height = handleHeight;
|
||||
}
|
||||
|
||||
// Setup sounds
|
||||
let currentWindowId = "window-wrapper-" + id;
|
||||
let currentWindow = document.getElementById(currentWindowId);
|
||||
}
|
||||
|
||||
function CloseButton(){
|
||||
const audio = new Audio('/sounds/close.wav');
|
||||
audio.type = "audio/wav"
|
||||
audio.play();
|
||||
if(typeof closeAction === 'function') closeAction();
|
||||
// ClearWindow(id)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if(props.custom) def.value = false;
|
||||
let win = GetWindowWithId(id);
|
||||
watch(GetWindowWithId(id), () => {
|
||||
resizable.value = win.resizable;
|
||||
})
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
setupHandle
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="window-handle" :id="'window-handle-' + id">
|
||||
|
||||
<div class="left" v-if="def">
|
||||
<img class="icon icon-add-margin" :src="ArrowLeftIcon" draggable="false" ref="backButton" v-if="hasBack" v-on:click="backFunction">
|
||||
</div>
|
||||
<div class="center" v-if="def">
|
||||
<span>{{ title }}</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<img class="icon" :src="XMarkIcon" draggable="false" ref="closeButton" v-if="close" v-on:click="CloseButton">
|
||||
</div>
|
||||
<!-- span>{{ title }}</span>
|
||||
|
||||
-->
|
||||
</div>
|
||||
|
||||
|
||||
<div v-show="resizable" class="window-resize-handle" :id="'window-resize-handle-' + id">
|
||||
<img :src="ResizeHandleIcon" draggable="false">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.window-resize-handle {
|
||||
position: absolute;
|
||||
filter: invert(0.8);
|
||||
opacity: 0.6;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
||||
img {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.window-handle {
|
||||
|
||||
.left, .right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.left {
|
||||
justify-content: left;
|
||||
}
|
||||
|
||||
.right {
|
||||
height: 24px;
|
||||
justify-content: right;
|
||||
}
|
||||
|
||||
span {
|
||||
font-family: MrEavesRemake;
|
||||
}
|
||||
|
||||
user-select: none;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
|
||||
background-color: var(--color-handler);
|
||||
}
|
||||
|
||||
</style>
|
||||
301
frontend/app/services/Windows.js
Normal file
301
frontend/app/services/Windows.js
Normal file
@@ -0,0 +1,301 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
const windows = ref([]);
|
||||
|
||||
import LoginWindow from '~/components/windows/LoginWindow.vue';
|
||||
|
||||
let windowMap = {
|
||||
login: LoginWindow
|
||||
};
|
||||
|
||||
async function InjectWindow(window_type, plugin, window_component) {
|
||||
let systemWidows = {};
|
||||
systemWidows[window_type] = (await import(`../../plugins/${plugin}/views/${window_component}.vue`)).default;
|
||||
windowMap = { ...windowMap, ...systemWidows };
|
||||
}
|
||||
|
||||
// Presets
|
||||
const defValues = {
|
||||
'login': {
|
||||
id: 'login',
|
||||
title: 'Login',
|
||||
}
|
||||
}
|
||||
|
||||
const reload = ref(0);
|
||||
|
||||
let ReloadRef = () => { return reload };
|
||||
let Windows = () => { return windows };
|
||||
let WindowMap = () => { return windowMap };
|
||||
|
||||
let currentIndex = 10;
|
||||
|
||||
function SetupHandle(id, handle) {
|
||||
|
||||
// Update window info with handle info
|
||||
|
||||
let win = GetWindowWithId(id);
|
||||
|
||||
let currentWindowId = "window-wrapper-" + id;
|
||||
let currentWindowHandleId = "window-handle-" + id;
|
||||
let currentWindowResizerId = "window-resize-handle-" + id;
|
||||
|
||||
let draggingWindow = false;
|
||||
let resizingWindow = false;
|
||||
|
||||
let currentWindow = document.getElementById(currentWindowId);
|
||||
let handler = document.getElementById(currentWindowHandleId);
|
||||
let resizer = document.getElementById(currentWindowResizerId);
|
||||
|
||||
let offsetX = 0;
|
||||
let offsetY = 0;
|
||||
|
||||
let resizeOffsetX = 0;
|
||||
let resizeOffsetY = 0;
|
||||
|
||||
// Programar un resizer mitjanament competent
|
||||
|
||||
currentWindow.addEventListener("mousedown", (event) => {
|
||||
SetOnTop(id);
|
||||
});
|
||||
|
||||
handler.addEventListener("mousedown", (event) => {
|
||||
draggingWindow = true;
|
||||
|
||||
let windowRect = currentWindow.getBoundingClientRect();
|
||||
offsetX = windowRect.left - event.clientX;
|
||||
offsetY = windowRect.top - event.clientY;
|
||||
})
|
||||
|
||||
// Move window listeners
|
||||
document.addEventListener("mousemove", (event) => {
|
||||
if (!draggingWindow) return;
|
||||
|
||||
if (event.clientX + offsetX < -currentWindow.getBoundingClientRect().width + 20) currentWindow.style.left = (-currentWindow.getBoundingClientRect().width + 20) + "px";
|
||||
else if (event.clientX + offsetX > window.innerWidth - 20) currentWindow.style.left = (window.innerWidth - 20) + "px";
|
||||
else currentWindow.style.left = (event.clientX + offsetX) + "px";
|
||||
|
||||
if (event.clientY + offsetY < 0) currentWindow.style.top = (0) + "px";
|
||||
else if (event.clientY + offsetY > window.innerHeight - 20) currentWindow.style.top = (window.innerHeight - 20) + "px";
|
||||
else currentWindow.style.top = (event.clientY + offsetY) + "px";
|
||||
})
|
||||
|
||||
document.addEventListener("mouseup", (event) => {
|
||||
draggingWindow = false;
|
||||
// ummm suposo que no pots tancar mentres mous?
|
||||
SaveWindowPos({ id, x: parseInt(currentWindow.style.left, 10), y: parseInt(currentWindow.style.top, 10) });
|
||||
});
|
||||
|
||||
// Resize window listeners
|
||||
resizer.addEventListener("mousedown", (event) => {
|
||||
resizingWindow = true;
|
||||
|
||||
let windowRect = currentWindow.getBoundingClientRect();
|
||||
resizeOffsetX = parseInt(currentWindow.style.width) - event.clientX;
|
||||
resizeOffsetY = parseInt(currentWindow.style.height) - event.clientY;
|
||||
});
|
||||
|
||||
document.addEventListener("mousemove", (event) => {
|
||||
if (!resizingWindow) return;
|
||||
|
||||
let newWidth = event.clientX + resizeOffsetX;
|
||||
let newHeight = event.clientY + resizeOffsetY;
|
||||
|
||||
if (win.minHeight) if (win.minHeight > newHeight) newHeight = win.minHeight;
|
||||
if (win.maxHeight) if (win.maxHeight < newHeight) newHeight = win.maxHeight;
|
||||
|
||||
if (win.minWidth) if (win.minWidth > newWidth) newWidth = win.minWidth;
|
||||
if (win.maxWidth) if (win.maxWidth < newWidth) newWidth = win.maxWidth;
|
||||
|
||||
currentWindow.style.width = newWidth + "px";
|
||||
currentWindow.style.height = newHeight + "px";
|
||||
});
|
||||
|
||||
document.addEventListener("mouseup", (event) => {
|
||||
resizingWindow = false;
|
||||
|
||||
win.width = parseInt(currentWindow.style.width, 10);
|
||||
win.height = parseInt(currentWindow.style.height, 10);
|
||||
});
|
||||
|
||||
handle.value.setupHandle();
|
||||
}
|
||||
|
||||
function SetResizable(id, resizable) {
|
||||
let win = GetWindowWithId(id);
|
||||
win.resizable = resizable;
|
||||
}
|
||||
|
||||
function SetSize(id, size) {
|
||||
let currentWindowId = "window-wrapper-" + id;
|
||||
let currentWindow = document.getElementById(currentWindowId);
|
||||
let win = GetWindowWithId(id);
|
||||
|
||||
currentWindow.style.width = size.width + "px";
|
||||
currentWindow.style.height = size.height + "px";
|
||||
|
||||
win.width = size.width;
|
||||
}
|
||||
|
||||
function SetMaxSize(id, maxSize) {
|
||||
let win = GetWindowWithId(id);
|
||||
|
||||
if (maxSize.width) win.maxWidth = maxSize.width;
|
||||
else win.maxWidth = win.width;
|
||||
|
||||
if (maxSize.height) win.maxHeight = maxSize.height;
|
||||
else win.maxHeight = win.height;
|
||||
}
|
||||
|
||||
function SetMinSize(id, minSize) {
|
||||
let win = GetWindowWithId(id);
|
||||
|
||||
if (minSize.width) win.minWidth = minSize.width;
|
||||
else win.minWidth = win.width;
|
||||
|
||||
if (minSize.height) win.minHeight = minSize.height;
|
||||
else win.minHeight = win.height;
|
||||
}
|
||||
|
||||
function SetPosition(id, pos) {
|
||||
let currentWindowId = "window-wrapper-" + id;
|
||||
let currentWindow = document.getElementById(currentWindowId);
|
||||
|
||||
if (pos == "center") {
|
||||
let x = window.innerWidth / 2;
|
||||
let y = window.innerHeight / 2;
|
||||
|
||||
currentWindow.style.left = (x - currentWindow.getBoundingClientRect().width / 2) + "px";
|
||||
currentWindow.style.top = (y - currentWindow.getBoundingClientRect().height / 2) + "px";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
currentWindow.style.top = pos.y + "px";
|
||||
currentWindow.style.left = pos.x + "px";
|
||||
|
||||
SaveWindowPos({ id, x: pos.x, y: pos.y })
|
||||
}
|
||||
|
||||
function GetPosition(id) {
|
||||
let win = GetWindowWithId(id);
|
||||
return { x: win.x, y: win.y };
|
||||
}
|
||||
|
||||
function ResetPosition(id, pos) {
|
||||
let win = GetWindowWithId(id);
|
||||
let data = { x: win.x, y: win.y };
|
||||
|
||||
if (data.x && data.y) {
|
||||
SetPosition(id, data);
|
||||
return;
|
||||
}
|
||||
SetPosition(id, pos);
|
||||
}
|
||||
|
||||
|
||||
function CreateWindow(type, data = {}) {
|
||||
|
||||
let finalData = { ...{ type }, ...defValues[type], ...data }
|
||||
console.log(finalData);
|
||||
|
||||
let contains = false;
|
||||
for (let i = 0; i < windows.value.length; i++) {
|
||||
if (windows.value[i].id == finalData.id) {
|
||||
contains = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!contains) {
|
||||
windows.value.push(finalData);
|
||||
console.log("Pushed ", finalData.id);
|
||||
// reload.value += 1;
|
||||
|
||||
console.log(windows.value);
|
||||
setTimeout(() => {
|
||||
SetOnTop(finalData.id);
|
||||
if (finalData.create) finalData.create();
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function CreateChildWindow(parentId, type, data = {}) {
|
||||
let finalData = { ...{ type }, ...defValues[type], ...data }
|
||||
|
||||
let parent = GetWindowWithId(parentId);
|
||||
if (parent.children) parent.children.push(finalData.id);
|
||||
else parent.children = [finalData.id];
|
||||
CreateWindow(type, data);
|
||||
}
|
||||
|
||||
function ClearAll() {
|
||||
Object.keys(windows).forEach((key) => {
|
||||
windows.value = [];
|
||||
});
|
||||
}
|
||||
|
||||
function ClearWindows(data) {
|
||||
for (let i = 0; i < windows.value.length; i++) {
|
||||
ClearWindow(windows.value[i].id);
|
||||
}
|
||||
// reload.value += 1;
|
||||
}
|
||||
|
||||
function ClearWindow(id) {
|
||||
let win = GetWindowWithId(id);
|
||||
if (!win) return;
|
||||
if (win.children) for (let i = 0; i < win.children.length; i++) ClearWindow(win.children[i]);
|
||||
windows.value = windows.value.filter((e) => { return e.id !== id });
|
||||
// reload.value += 1;
|
||||
}
|
||||
|
||||
function GetWindowWithId(id) {
|
||||
for (let i = 0; i < windows.value.length; i++) {
|
||||
if (windows.value[i].id == id) {
|
||||
return windows.value[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function CallWindow(id, callableName, arg) {
|
||||
let win = GetWindowWithId(id);
|
||||
win[callableName](arg);
|
||||
}
|
||||
|
||||
function SaveWindowPos(data) {
|
||||
let win = GetWindowWithId(data.id);
|
||||
if (win === undefined) return;
|
||||
win.x = data.x;
|
||||
win.y = data.y;
|
||||
}
|
||||
|
||||
function SetOnTop(id) {
|
||||
let currentWindowId = "window-wrapper-" + id;
|
||||
let currentWindow = document.getElementById(currentWindowId);
|
||||
|
||||
currentIndex += 1;
|
||||
currentWindow.style.zIndex = currentIndex;
|
||||
}
|
||||
|
||||
export {
|
||||
SetupHandle,
|
||||
SetSize,
|
||||
SetResizable,
|
||||
SetMaxSize,
|
||||
SetMinSize,
|
||||
SetPosition,
|
||||
ResetPosition,
|
||||
Windows,
|
||||
WindowMap,
|
||||
InjectWindow,
|
||||
ReloadRef,
|
||||
ClearWindows,
|
||||
CreateWindow,
|
||||
CreateChildWindow,
|
||||
CallWindow,
|
||||
GetWindowWithId,
|
||||
SaveWindowPos,
|
||||
GetPosition,
|
||||
ClearWindow,
|
||||
ClearAll
|
||||
}
|
||||
Reference in New Issue
Block a user