Compare commits

...

8 Commits

25 changed files with 677 additions and 320 deletions

View File

@ -1,8 +1,9 @@
package blogviewer package blogviewer
import ( import (
"net/http"
"personalwebsite/apps"
"personalwebsite/webfilesystem" "personalwebsite/webfilesystem"
"personalwebsite/websiteapp"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
@ -10,20 +11,20 @@ import (
type BlogViewerApplication struct { type BlogViewerApplication struct {
fs *webfilesystem.WebFileSystem fs *webfilesystem.WebFileSystem
manifest websiteapp.ApplicationManifest manifest apps.ApplicationManifest
} }
func NewBlogViewerApp(webFs *webfilesystem.WebFileSystem) *BlogViewerApplication { func NewBlogViewerApp(webFs *webfilesystem.WebFileSystem) *BlogViewerApplication {
return &BlogViewerApplication{ return &BlogViewerApplication{
fs: webFs, fs: webFs,
manifest: websiteapp.ApplicationManifest{ manifest: apps.ApplicationManifest{
AppId: "blog-viewer", AppId: "blog-viewer",
WindowName: "", WindowName: "",
}, },
} }
} }
func (b *BlogViewerApplication) GetManifest() websiteapp.ApplicationManifest { func (b *BlogViewerApplication) GetManifest() apps.ApplicationManifest {
return b.manifest return b.manifest
} }
@ -31,6 +32,41 @@ func (b *BlogViewerApplication) GetId() string {
return b.manifest.AppId return b.manifest.AppId
} }
func (b *BlogViewerApplication) Route(route *gin.RouterGroup) {
route.GET("writeMockBlog", func(ctx *gin.Context) {
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "no path provided")
return
}
b.WriteMock(path)
ctx.JSON(http.StatusOK, "OK")
})
route.GET("render", func(ctx *gin.Context) {
isMobileParam := ctx.Query("isMobile")
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "no path provided")
return
}
isMobile := isMobileParam == "true"
ginH, err := b.Render(path, isMobile)
if err != nil {
ctx.JSON(http.StatusInternalServerError, "TODO")
return
}
if isMobile {
ctx.HTML(http.StatusOK, "blog-viewer/mobile-app.tmpl", ginH)
} else {
ctx.HTML(http.StatusOK, "blog-viewer/app.tmpl", ginH)
}
})
}
func (b *BlogViewerApplication) WriteMock(path string) { func (b *BlogViewerApplication) WriteMock(path string) {
blogFile := webfilesystem.WebFSFile{ blogFile := webfilesystem.WebFSFile{
MongoId: primitive.NewObjectID(), MongoId: primitive.NewObjectID(),

67
apps/finder/finder.go Normal file
View File

@ -0,0 +1,67 @@
package finder
import (
"net/http"
"personalwebsite/apps"
"personalwebsite/webfilesystem"
"github.com/gin-gonic/gin"
)
type FinderApplication struct {
fs *webfilesystem.WebFileSystem
manifest apps.ApplicationManifest
}
func NewFinderApplication(webFs *webfilesystem.WebFileSystem) *FinderApplication {
return &FinderApplication{
fs: webFs,
manifest: apps.ApplicationManifest{
AppId: "finder",
WindowName: "TODO DELETE", //TODO DELETE
},
}
}
func (f *FinderApplication) GetManifest() apps.ApplicationManifest {
return f.manifest
}
func (f *FinderApplication) GetId() string {
return f.manifest.AppId
}
func (f *FinderApplication) Render(isMobile bool) gin.H {
return gin.H{}
}
func (f *FinderApplication) Routes(routes *gin.RouterGroup) {
routes.GET("render", func(ctx *gin.Context) {
isMobileParam := ctx.Query("isMobile")
isMobile := isMobileParam == "true"
admin := true
if isMobile {
ctx.HTML(http.StatusOK, "finder/mobile-app.tmpl", f.Render(isMobile))
return
}
if admin {
ctx.HTML(http.StatusOK, "finder/admin-app.tmpl", f.Render(isMobile))
return
}
ctx.HTML(http.StatusOK, "finder/app.tmpl", f.Render(isMobile))
})
routes.GET("renderMobileDesktop", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "finder/mobile-desktop.tmpl", gin.H{})
})
routes.GET("renderDesktop", func(ctx *gin.Context) {
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "no path provided")
return
}
ctx.HTML(http.StatusOK, "finder/desktop.tmpl", gin.H{})
})
routes.GET("contextMenu", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "wde-widgets/context-menu.tmpl", gin.H{})
})
}

View File

@ -0,0 +1,22 @@
package finder
import (
"personalwebsite/apps"
"personalwebsite/webfilesystem"
)
type FinderAdminApp struct {
fs *webfilesystem.WebFileSystem
manifest apps.ApplicationManifest
}
func NewFinderAdminApp(webfs *webfilesystem.WebFileSystem) FinderAdminApp {
return FinderAdminApp{
fs: webfs,
manifest: apps.ApplicationManifest{},
}
}
func (f *FinderAdminApp) RenderWindow() {
}

View File

@ -1,9 +1,10 @@
package imgviewer package imgviewer
import ( import (
"net/http"
websiteapp "personalwebsite/apps"
"personalwebsite/libs" "personalwebsite/libs"
"personalwebsite/webfilesystem" "personalwebsite/webfilesystem"
"personalwebsite/websiteapp"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@ -24,6 +25,28 @@ func NewImgViewerApp(webFs *webfilesystem.WebFileSystem) ImgViewerApp {
return newApp return newApp
} }
func (p *ImgViewerApp) Route(route *gin.RouterGroup) {
route.GET("render", func(ctx *gin.Context) {
isMobileParam := ctx.Query("isMobile")
isMobile := isMobileParam == "true"
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "no path provided")
return
}
ginH, err := p.Render(path, isMobile)
if err != nil {
ctx.JSON(http.StatusInternalServerError, "TODO")
return
}
if isMobile {
ctx.HTML(http.StatusOK, "img-viewer/mobile-app.tmpl", ginH)
} else {
ctx.HTML(http.StatusOK, "img-viewer/app.tmpl", ginH)
}
})
}
func (p *ImgViewerApp) GetManifest() websiteapp.ApplicationManifest { func (p *ImgViewerApp) GetManifest() websiteapp.ApplicationManifest {
return p.manifest return p.manifest
} }

View File

@ -2,9 +2,10 @@ package personalprops
import ( import (
"errors" "errors"
"net/http"
websiteapp "personalwebsite/apps"
"personalwebsite/libs" "personalwebsite/libs"
"personalwebsite/webfilesystem" "personalwebsite/webfilesystem"
"personalwebsite/websiteapp"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
@ -26,6 +27,22 @@ func NewPersPropsApp(webFs *webfilesystem.WebFileSystem) PersonalPropertiesApp {
return newApp return newApp
} }
func (p *PersonalPropertiesApp) Route(route *gin.RouterGroup) {
route.GET("render", func(ctx *gin.Context) {
isMobileParam := ctx.Query("isMobile")
isMobile := isMobileParam == "true"
ginH, err := p.Render()
if err != nil {
ctx.JSON(http.StatusInternalServerError, "TODO") //TODO
}
if isMobile {
ctx.HTML(http.StatusOK, "personal-properties/mobile-app.tmpl", ginH)
} else {
ctx.HTML(http.StatusOK, "personal-properties/app.tmpl", ginH)
}
})
}
func (p *PersonalPropertiesApp) GetManifest() websiteapp.ApplicationManifest { func (p *PersonalPropertiesApp) GetManifest() websiteapp.ApplicationManifest {
return p.manifest return p.manifest
} }

View File

@ -1,4 +1,4 @@
package websiteapp package apps
import ( import (
"net/http" "net/http"

View File

@ -2,8 +2,10 @@ package libs
import ( import (
"errors" "errors"
"net/http"
"personalwebsite/webfilesystem" "personalwebsite/webfilesystem"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
) )
@ -11,6 +13,12 @@ type ImagLib struct {
fs *webfilesystem.WebFileSystem fs *webfilesystem.WebFileSystem
} }
func NewImgLib(webfs *webfilesystem.WebFileSystem) *ImagLib {
return &ImagLib{
fs: webfs,
}
}
func ReadImage(img *webfilesystem.WebFSFile) (*Img, error) { func ReadImage(img *webfilesystem.WebFSFile) (*Img, error) {
data, ok := img.Data.(primitive.D).Map()["srcdata"] data, ok := img.Data.(primitive.D).Map()["srcdata"]
if !ok { if !ok {
@ -30,6 +38,25 @@ func ReadImage(img *webfilesystem.WebFSFile) (*Img, error) {
}, nil }, nil
} }
func (l *ImagLib) Route(route *gin.RouterGroup) {
route.GET("get", func(ctx *gin.Context) {
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "TODO") //TODO json error struct
return
}
file, err := l.fs.Read(path)
if err != nil {
ctx.String(http.StatusInternalServerError, "TODO") //TODO
}
data := file.Data.(primitive.Binary)
ctx.Data(http.StatusOK, "image/jpeg", data.Data)
})
}
func GetBase64Image(img *Base64Img, min string) (string, error) { func GetBase64Image(img *Base64Img, min string) (string, error) {
imgString := "" imgString := ""
switch min { switch min {

15
libs/libs.go Normal file
View File

@ -0,0 +1,15 @@
package libs
import (
"personalwebsite/webfilesystem"
)
type Libs struct {
imglib *ImagLib
}
func NewLibs(webfs *webfilesystem.WebFileSystem) Libs {
return Libs{
imglib: NewImgLib(webfs),
}
}

205
main.go
View File

@ -8,19 +8,19 @@ import (
"net/http" "net/http"
"os" "os"
"personalwebsite/apps"
"personalwebsite/apps/blogviewer"
"personalwebsite/apps/finder"
imgviewer "personalwebsite/apps/img-viewer"
"personalwebsite/apps/personalprops"
"personalwebsite/libs"
"personalwebsite/routewde" "personalwebsite/routewde"
"personalwebsite/wde" "personalwebsite/wde"
"personalwebsite/webfilesystem" "personalwebsite/webfilesystem"
"personalwebsite/websiteapp"
"personalwebsite/websiteapp/blogviewer"
"personalwebsite/websiteapp/finder"
imgviewer "personalwebsite/websiteapp/img-viewer"
"personalwebsite/websiteapp/personalprops"
"github.com/gin-contrib/location" "github.com/gin-contrib/location"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/joho/godotenv" "github.com/joho/godotenv"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/options"
) )
@ -74,8 +74,8 @@ func main() {
finderApp := finder.NewFinderApplication(webfs) finderApp := finder.NewFinderApplication(webfs)
imgViewerApp := imgviewer.NewImgViewerApp(webfs) imgViewerApp := imgviewer.NewImgViewerApp(webfs)
blogViewerApp := blogviewer.NewBlogViewerApp(webfs) blogViewerApp := blogviewer.NewBlogViewerApp(webfs)
appsStorage := websiteapp.ApplicationsStorage{ appsStorage := apps.ApplicationsStorage{
Apps: map[string]websiteapp.WebDEApplication{}, Apps: map[string]apps.WebDEApplication{},
} }
appsStorage.Apps["personal-properties"] = &persPropsApp appsStorage.Apps["personal-properties"] = &persPropsApp
appsStorage.Apps["finder"] = finderApp appsStorage.Apps["finder"] = finderApp
@ -119,21 +119,8 @@ func main() {
{ {
imgLibGroup := libsGroup.Group("img") imgLibGroup := libsGroup.Group("img")
{ {
imgLibGroup.GET("get", func(ctx *gin.Context) { imgLib := libs.NewImgLib(webfs)
path := ctx.Query("path") imgLib.Route(imgLibGroup)
if path == "" {
ctx.JSON(http.StatusBadRequest, "TODO") //TODO json error struct
return
}
file, err := webfs.Read(path)
if err != nil {
ctx.String(http.StatusInternalServerError, "TODO") //TODO
}
data := file.Data.(primitive.Binary)
ctx.Data(http.StatusOK, "image/jpeg", data.Data)
})
} }
} }
wdeGroup := system.Group("wde") wdeGroup := system.Group("wde")
@ -163,193 +150,41 @@ func main() {
} }
}) })
} }
websiteapp.Route(apps.Group("/storage"), &appsStorage)
} }
fs := router.Group("fs") fs := router.Group("fs")
{ {
fs.GET("writeFile", func(ctx *gin.Context) { webfs.Route(fs)
parentPath := ctx.Query("parentPath")
if parentPath == "" {
ctx.JSON(http.StatusBadRequest, "TODO") //TODO json error struct
return
}
file := webfilesystem.WebFSFile{
MongoId: primitive.NewObjectID(),
Name: "pp",
Type: "test",
Data: nil,
}
err := webfs.CreateFile(&file, parentPath)
if err != nil {
ctx.JSON(http.StatusInternalServerError, "TODO") //TODO json error struct
return
}
ctx.JSON(http.StatusOK, "OK")
})
fs.GET("createDir", func(ctx *gin.Context) {
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "TODO") //TODO json error struct
return
}
err := webfs.CreateDirectory(path)
if err != nil {
ctx.JSON(http.StatusInternalServerError, "TODO") //TODO json error struct
return
}
ctx.JSON(http.StatusOK, "OK")
})
fs.GET("list", func(ctx *gin.Context) {
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "TODO") //TODO json error struct
return
}
files, err := webfs.List(path)
if err != nil {
ctx.JSON(http.StatusInternalServerError, "TODO") //TODO json error struct
return
}
ctx.JSON(http.StatusOK, &files)
})
fs.GET("read", func(ctx *gin.Context) {
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "TODO") //TODO json error struct
return
}
file, err := webfs.Read(path)
if err != nil {
ctx.JSON(http.StatusInternalServerError, "TODO") //TODO json error struct
return
}
ctx.JSON(http.StatusOK, &file)
})
} }
app := router.Group("application") app := router.Group("application")
{ {
persPropApp := app.Group("personal-properties") persPropApp := app.Group("personal-properties")
{ {
persPropApp.GET("render", func(ctx *gin.Context) { persPropsApp.Route(persPropApp)
isMobileParam := ctx.Query("isMobile")
isMobile := isMobileParam == "true"
ginH, err := persPropsApp.Render()
if err != nil {
ctx.JSON(http.StatusInternalServerError, "TODO") //TODO
}
if isMobile {
ctx.HTML(http.StatusOK, "personal-properties/mobile-app.tmpl", ginH)
} else {
ctx.HTML(http.StatusOK, "personal-properties/app.tmpl", ginH)
}
})
} }
finderAppRoute := app.Group("finder") finderAppRoute := app.Group("finder")
{ {
finderAppRoute.GET("render", func(ctx *gin.Context) { finderApp.Routes(finderAppRoute)
isMobileParam := ctx.Query("isMobile")
isMobile := isMobileParam == "true"
if isMobile {
ctx.HTML(http.StatusOK, "finder/mobile-app.tmpl", finderApp.Render(isMobile))
} else {
ctx.HTML(http.StatusOK, "finder/app.tmpl", finderApp.Render(isMobile))
}
})
finderAppRoute.GET("renderMobileDesktop", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "finder/mobile-desktop.tmpl", gin.H{})
})
finderAppRoute.GET("renderDesktop", func(ctx *gin.Context) {
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "no path provided")
return
}
ctx.HTML(http.StatusOK, "finder/desktop.tmpl", gin.H{})
})
} }
imgViewerRoute := app.Group("img-viewer") imgViewerRoute := app.Group("img-viewer")
{ {
imgViewerRoute.GET("render", func(ctx *gin.Context) { imgViewerApp.Route(imgViewerRoute)
isMobileParam := ctx.Query("isMobile")
isMobile := isMobileParam == "true"
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "no path provided")
return
}
ginH, err := imgViewerApp.Render(path, isMobile)
if err != nil {
ctx.JSON(http.StatusInternalServerError, "TODO")
return
}
if isMobile {
ctx.HTML(http.StatusOK, "img-viewer/mobile-app.tmpl", ginH)
} else {
ctx.HTML(http.StatusOK, "img-viewer/app.tmpl", ginH)
}
})
} }
blogViewerRoute := app.Group("blog-viewer") blogViewerRoute := app.Group("blog-viewer")
{ {
blogViewerRoute.GET("writeMockBlog", func(ctx *gin.Context) { blogViewerApp.Route(blogViewerRoute)
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "no path provided")
return
}
blogViewerApp.WriteMock(path)
ctx.JSON(http.StatusOK, "OK")
})
blogViewerRoute.GET("render", func(ctx *gin.Context) {
isMobileParam := ctx.Query("isMobile")
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "no path provided")
return
} }
isMobile := isMobileParam == "true" err = router.Run(":8080")
ginH, err := blogViewerApp.Render(path, isMobile)
if err != nil { if err != nil {
ctx.JSON(http.StatusInternalServerError, "TODO")
return
}
if isMobile {
ctx.HTML(http.StatusOK, "blog-viewer/mobile-app.tmpl", ginH)
} else {
ctx.HTML(http.StatusOK, "blog-viewer/app.tmpl", ginH)
}
})
}
}
router.GET("/test", func(ctx *gin.Context) {
ctx.HTML(200, "kek/kek.tmpl", gin.H{})
})
if err := router.Run(":8080"); err != nil {
log.Panicf("error: %s", err) log.Panicf("error: %s", err)
} }
}
} }
func index(c *gin.Context) { // func index(c *gin.Context) {
c.HTML(http.StatusOK, "base.html", nil) // c.HTML(http.StatusOK, "base.html", nil)
} // }
func FindEnv(parameter string) (string, error) { func FindEnv(parameter string) (string, error) {
path, exists := os.LookupEnv(parameter) path, exists := os.LookupEnv(parameter)

View File

@ -0,0 +1,39 @@
.FinderContent {
width: 100%;
height: 100%;
/* Auto layout */
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
padding: 0px;
}
.FinderContent .ToolBar{
width: 100%;
height: 20px;
border-bottom: 1px solid #555555;
background-color: #EEEEEE;
}
.Focused .FinderContent .ToolBar{
border-bottom: 1px solid #000000;
background-color: #DDDDDD;
}
.FinderContent .FinderFileView{
width: 100%;
height: 100%;
background-color: #FFFFFF;
/* Auto layout */
display: flex;
flex-direction: row;
justify-content: center;
align-items: flex-start;
padding: 0px;
}

View File

@ -3,6 +3,7 @@ class Finder{
fileView = undefined fileView = undefined
path = "/" path = "/"
homePath = "/home/user" homePath = "/home/user"
windowElement
// previousPath = "/" // previousPath = "/"
pathHistory = [] //FIXME Fixed length pathHistory = [] //FIXME Fixed length
constructor(){ constructor(){
@ -28,9 +29,9 @@ class Finder{
let newWindow = WebDesktopEnvironment.CreateNewWindow(this.appId, 500, 350 ) let newWindow = WebDesktopEnvironment.CreateNewWindow(this.appId, 500, 350 )
newWindow.innerHTML = html newWindow.innerHTML = html
this.fileView = new FileView(newWindow.querySelector(".FileTileView"), (event) =>{ this.fileView = new FileView(newWindow.querySelector(".FileTileView"),
this.Open(event, false) (event) =>{ this.Open(event, false) },
}) (event) =>{ this.RightClick(event) })
this.OpenDir(this.path) this.OpenDir(this.path)
newWindow.querySelector("#BackButton").addEventListener('click', () =>{ newWindow.querySelector("#BackButton").addEventListener('click', () =>{
@ -41,6 +42,8 @@ class Finder{
this.OpenDir(this.homePath) this.OpenDir(this.homePath)
}) })
this.windowElement = newWindow
if (!WebDesktopEnvironment.isMobile){ if (!WebDesktopEnvironment.isMobile){
// let scrollBar = new WdeScrollBar(newWindow.children[1].children[1], newWindow.children[1].children[0])// TODO to querry selector // let scrollBar = new WdeScrollBar(newWindow.children[1].children[1], newWindow.children[1].children[0])// TODO to querry selector
// console.log(newWindow.querySelector("#closeWindowButton")) // console.log(newWindow.querySelector("#closeWindowButton"))
@ -139,6 +142,55 @@ class Finder{
} }
} }
RightClick(event){
// console.log(event)
// console.log()
if (event.target.className="FileTileView" ||event.target.getAttribute('filetype') != ""){
this.CreateContextMenu(event.target, [event.clientY, event.clientX])
}
}
CreateContextMenu(target, pos){
fetch(`${window.location.origin}/application/${this.appId}/contextMenu?` + new URLSearchParams({
kek: "kek"
}))
.then((response) => response.text())
.then((html) => {
let overlay = document.createElement("div") //TODO Move to WDE.CreateOverlay()
overlay.setAttribute('id', 'finder-context-menu-overlay')
overlay.style.position = 'absolute'
overlay.style.width = "100%"
overlay.style.height = "100%"
let menu = document.createElement("div")
menu.setAttribute('class', 'ContextMenu WindowFrameShadow')
menu.style.position = 'absolute';
// menu.style.backgroundColor = '#000000';
menu.style.top = pos[0] + "px";
menu.style.left = pos[1] + "px";
menu.innerHTML = html
overlay.appendChild(menu)
document.body.appendChild(overlay)
overlay.addEventListener('click',(event) => {
if (event.target.className == "Row"){ //TODO add uuid id to rows to more accurate checks??
// console.log("aaaa")
}
overlay.remove()
})
overlay.addEventListener('contextmenu', (event) => {
event.preventDefault();
overlay.remove()
})
})
.catch((error) => {
WebDesktopEnvironment.Alert(error);
})
}
// /** // /**
// * @param {path} string // * @param {path} string
// */ // */

View File

@ -0,0 +1,60 @@
.ContentBorder { /*TODO Delete, deprecated*/
width: 100%;
height: 100%;
/* background-color: #DDDDDD;
border: 1px solid #000000; */
overflow: hidden;
overflow-x: hidden;
}
.ContextMenu {
position: absolute;
width: auto;
height: auto;
background-color: #DDDDDD;
border: 1px solid #000000;
}
.ContextMenu .Content{
position: relative;
width: auto;
height: auto;
/* Auto layout */
display: flex;
flex-direction: column;
align-items: flex-start;
/* padding: 4px;
padding-top: 2px;
padding-right: 6px;
gap: 4px; */
}
.ContextMenu .Row {
width: 100%;
height: 16px;
}
.ContextMenu .SectionBreaker {
/* background-color: rebeccapurple; */
}
.ContextMenu .Row:hover{
background-color: #333399;
color: #FFFFFF;
}
.ContextMenu .Row .Lable{
margin-left: 20px;
margin-right: 12px;
font-family: "Virtue";
white-space: nowrap;
}

View File

@ -2,6 +2,8 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
/* FIXME Bug, on desktop mode top ~10 pixel are not active, like margin:10px */ /* FIXME Bug, on desktop mode top ~10 pixel are not active, like margin:10px */
} }

View File

@ -4,8 +4,9 @@ class FileView{
/** /**
* @param {HTMLElement} fileViewElem * @param {HTMLElement} fileViewElem
* @param {Function} doubleClickCallback * @param {Function} doubleClickCallback
* @param {Function} rightClickCallback
*/ */
constructor(fileViewElem, doubleClickCallback){ constructor(fileViewElem, doubleClickCallback, rightClickCallback){
//TODO check all params //TODO check all params
this.parentElem = fileViewElem this.parentElem = fileViewElem
@ -23,6 +24,11 @@ class FileView{
doubleClickCallback(event) doubleClickCallback(event)
} }
}) })
fileViewElem.addEventListener('contextmenu', (event) => {
event.preventDefault();
rightClickCallback(event)
})
} }
DeselectAll(){ DeselectAll(){

View File

@ -16,7 +16,7 @@
.ScrollbarPlace{ .ScrollbarPlace{
overflow: hidden; overflow: hidden;
border-left: 1px solid #000000; border-left: 1px solid #555555;
width: 14px; width: 14px;
height: 100%; height: 100%;
@ -25,8 +25,8 @@
width: 14px; width: 14px;
height: 100%; height: 100%;
background-color: #AAAAAA; background-color: #EEEEEE;
box-shadow: inset -1px 0px 0px rgba(255, 255, 255, 0.29), inset -2px 0px 0px rgba(255, 255, 255, 0.19), inset 1px 1px 0px rgba(0, 0, 0, 0.14), inset 2px 2px 0px rgba(0, 0, 0, 0.19);
/* Inside auto layout */ /* Inside auto layout */
flex: none; flex: none;
@ -35,16 +35,32 @@
flex-grow: 1; flex-grow: 1;
} }
.Focused .ScrollbarPlace{
border-left: 1px solid #000000;
background-color: #AAAAAA;
box-shadow: inset -1px 0px 0px rgba(255, 255, 255, 0.29),
inset -2px 0px 0px rgba(255, 255, 255, 0.19),
inset 1px 1px 0px rgba(0, 0, 0, 0.14),
inset 2px 2px 0px rgba(0, 0, 0, 0.19);
}
.ScrollBarScrollElement{ .ScrollBarScrollElement{
position: relative; position: relative;
visibility: hidden;
width: 14px; width: 14px;
height: 31px; height: 31px;
background: #9999FF; background: #9999FF;
box-shadow: 0px -1px 0px #000000, 0px 1px 0px #000000, 0px 2px 0px rgba(0, 0, 0, 0.13), 0px 3px 0px rgba(0, 0, 0, 0.19), inset 0px 1px 0px rgba(255, 255, 255, 0.5), inset 1px 0px 0px rgba(255, 255, 255, 0.5), inset -1px -1px 0px rgba(102, 102, 204, 0.91); box-shadow: 0px -1px 0px #000000,
0px 1px 0px #000000,
0px 2px 0px rgba(0, 0, 0, 0.13),
0px 3px 0px rgba(0, 0, 0, 0.19),
inset 0px 1px 0px rgba(255, 255, 255, 0.5),
inset 1px 0px 0px rgba(255, 255, 255, 0.5),
inset -1px -1px 0px rgba(102, 102, 204, 0.91);
/* Auto layout */
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
@ -53,6 +69,10 @@
padding: 0px; padding: 0px;
} }
.Focused .ScrollBarScrollElement{
visibility: visible;
}
.ScrollBarScrollElementDrag{ .ScrollBarScrollElementDrag{
pointer-events: none; pointer-events: none;
/* background-color: #0A4C95; */ /* background-color: #0A4C95; */

View File

@ -4,7 +4,7 @@ document.addEventListener('DOMContentLoaded', function() {
// console.log(window.screen.width) // console.log(window.screen.width)
wde = new WebDesktopEnvironment wde = new WebDesktopEnvironment
if (!WebDesktopEnvironment.isMobile){ if (!WebDesktopEnvironment.isMobile){
// WebDesktopEnvironment.Open("finder", ["/home/user"]) WebDesktopEnvironment.Open("finder", ["/home/user"])
// WebDesktopEnvironment.Open("blog-viewer", ["/home/user/blog/test-1.blog"]) // WebDesktopEnvironment.Open("blog-viewer", ["/home/user/blog/test-1.blog"])
// WebDesktopEnvironment.Open("personal-properties", ["kek"]) // WebDesktopEnvironment.Open("personal-properties", ["kek"])
} else { } else {
@ -143,13 +143,14 @@ class WebDesktopEnvironment{
document.body.querySelector('#windows-layer').appendChild(newWindow) document.body.querySelector('#windows-layer').appendChild(newWindow)
return newWindow return newWindow
} else { } else {
newWindow.setAttribute("class", "WindowFrame") newWindow.setAttribute("class", "WindowFrame ConvexElement")
newWindow.setAttribute("windowId", "SuperUniqUUID") //TODO: newWindow.setAttribute("windowId", "SuperUniqUUID") //TODO:
newWindow.style.width = width.toString() + "px" newWindow.style.width = width.toString() + "px"
newWindow.style.height = height.toString() + "px" newWindow.style.height = height.toString() + "px"
document.body.querySelector('#windows-layer').appendChild(newWindow) document.body.querySelector('#windows-layer').appendChild(newWindow)
WindowsCompositor.bringWindowToFront(newWindow)
return newWindow return newWindow
} }
} }
@ -249,11 +250,7 @@ class WindowsCompositor{
let startDrag = function(event) { let startDrag = function(event) {
let window = event.target.closest('.WindowFrame') let window = event.target.closest('.WindowFrame')
WindowsCompositor.bringWindowToFront(window) WindowsCompositor.bringWindowToFront(window)
let targetClasses = event.target.className.split(' ') if (event.target.classList.contains("DragArea")){
if (targetClasses[targetClasses.length - 1] != 'DragArea'){
return
}
let xPosInit = event.offsetX let xPosInit = event.offsetX
let yPosInit = event.offsetY let yPosInit = event.offsetY
let dragWindow = function(event){ let dragWindow = function(event){
@ -268,7 +265,7 @@ class WindowsCompositor{
addEventListener('mousemove', dragWindow) addEventListener('mousemove', dragWindow)
addEventListener('mouseup', stopDrag) addEventListener('mouseup', stopDrag)
} }
}
WindowsCompositor.windowsLayer.addEventListener('mousedown', startDrag) WindowsCompositor.windowsLayer.addEventListener('mousedown', startDrag)
} }
} }
@ -277,7 +274,10 @@ class WindowsCompositor{
* @param {HTMLElement} window * @param {HTMLElement} window
*/ */
static bringWindowToFront(window){ //FIXME static bringWindowToFront(window){ //FIXME
if (window != WindowsCompositor.windowsLayer.lastChild ){ if (!window.classList.contains("Focused")){
let previousWindow = WindowsCompositor.windowsLayer.lastChild
previousWindow.classList.remove("Focused")
window.classList.add("Focused")
WindowsCompositor.windowsLayer.insertBefore(WindowsCompositor.windowsLayer.lastChild, window) WindowsCompositor.windowsLayer.insertBefore(WindowsCompositor.windowsLayer.lastChild, window)
} }
} }

View File

@ -1,4 +1,4 @@
.WindowFrame{ .WindowFrame {
/* Auto layout */ /* Auto layout */
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -10,9 +10,9 @@
position: absolute; position: absolute;
background: #CCCCCC; background: #DDDDDD;
border: 1px solid #000000; border: 1px solid #555555;
box-shadow: 1px 1px 0px rgba(0, 0, 0, 0.25), inset -1px -1px 0px rgba(0, 0, 0, 0.27), inset 1px 1px 0px #FFFFFF;
/* Inside auto layout */ /* Inside auto layout */
flex: none; flex: none;
@ -21,36 +21,55 @@
flex-grow: 1; flex-grow: 1;
} }
.ContentBorder { /* TODO Add shadows to windows */
width: 100%; .WindowFrame.Focused{
height: 100%;
background-color: #DDDDDD;
border: 1px solid #000000; border: 1px solid #000000;
background-color: #CCCCCC;
box-shadow: -1px -1px 0px rgba(0, 0, 0, 0.25),
1px 1px 0px #FFFFFF,
inset -1px -1px 0px rgba(0, 0, 0, 0.27),
inset 1px 1px 0px #FFFFFF;
overflow: hidden;
overflow-x: hidden;
/* Auto layout */
display: flex;
flex-direction: row;
justify-content: center;
align-items: flex-start;
padding: 0px;
} }
.WindowFrame .TitleBar{ .WindowFrameShadow {
box-shadow: 2px 2px 0px #555555;
}
.Focused .WindowFrameShadow {
box-shadow: 2px 2px 0px #000000;
}
.Focused .ConvexElement {
box-shadow: 1px 1px 0px rgba(0, 0, 0, 0.25),
inset -1px -1px 0px rgba(0, 0, 0, 0.27),
inset 1px 1px 0px #FFFFFF;
}
.AdjectiveElement {
border: 1px solid #555555;
}
.Focused .AdjectiveElement {
border: 1px solid #000000;
box-shadow: -1px -1px 0px rgba(0, 0, 0, 0.25),
1px 1px 0px #FFFFFF;
/* inset -1px -1px 0px rgba(0, 0, 0, 0.27), */
/* inset 1px 1px 0px #FFFFFF;*/
}
.AdjectiveHorizontalLine {
border-top: 1px solid rgba(0, 0, 0, 0.25);
border-bottom: 1px solid #FFFFFF;
width: 100%;
height: 0px;
}
.WindowFrame .TitleBar {
width: 100%; width: 100%;
height: 13px; height: 13px;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
justify-content: space-between; justify-content: center;
gap: 5px; gap: 5px;
padding: 0px; padding: 0px;
@ -62,12 +81,11 @@
flex-grow: 0; flex-grow: 0;
} }
.WindowFrame .TitleBar .Lable {
.WindowFrame .TitleBar .Lable{
position: relative; position: relative;
top:1px; top: 1px;
/* font-size: 13px; */ /* font-size: 13px; */
color:#777777;
pointer-events: none; pointer-events: none;
white-space: nowrap; white-space: nowrap;
@ -75,13 +93,18 @@
letter-spacing: 0.35px; letter-spacing: 0.35px;
} }
.WindowFrame.Focused .TitleBar .Lable {
color:#000000;
}
.WindowFrame .TitleBar .Button{
.WindowFrame .TitleBar .Button {
width: 11px; width: 11px;
height: 11px; height: 11px;
padding: 0%; padding: 0%;
position: relative; position: relative;
top: 1px; top: 1px;
visibility: hidden;
background: linear-gradient(135deg, #999999 18.18%, #FFFFFF 81.82%); background: linear-gradient(135deg, #999999 18.18%, #FFFFFF 81.82%);
border: 1px solid #222222; border: 1px solid #222222;
@ -89,24 +112,28 @@
-0.5px -0.5px 0px 0.5px rgba(0, 0, 0, 0.25), -0.5px -0.5px 0px 0.5px rgba(0, 0, 0, 0.25),
inset 1px 1px 0px rgba(255, 255, 255, 0.5), inset 1px 1px 0px rgba(255, 255, 255, 0.5),
inset -1px -1px 0px rgba(0, 0, 0, 0.27); inset -1px -1px 0px rgba(0, 0, 0, 0.27);
/* Inside auto layout */ /* Inside auto layout */
flex: none; flex: none;
order: 0; order: 0;
flex-grow: 0; flex-grow: 0;
} }
.WindowFrame.Focused .TitleBar .Button {
visibility: visible;
}
.WindowFrame .TitleBar .Button:active { .WindowFrame .TitleBar .Button:active {
background-color: rgba(0, 0, 0, 0.4); /* Green */ background-color: rgba(0, 0, 0, 0.4);
/* Green */
box-shadow: 0.5px 0.5px 0px 0.5px #FFFFFF, box-shadow: 0.5px 0.5px 0px 0.5px #FFFFFF,
-0.5px -0.5px 0px 0.5px rgba(0, 0, 0, 0.25); -0.5px -0.5px 0px 0.5px rgba(0, 0, 0, 0.25);
} }
.WindowFrame .TitleBar .VisualDragArea{ .Focused .VisualDragArea {
pointer-events: none; pointer-events: none;
width: 100%; width: 100%;
height: 11px; height: 11px;
background: linear-gradient(transparent 0%,white 0%, white 50%, transparent 50%); background: linear-gradient(transparent 0%, white 0%, white 50%, transparent 50%);
background-size: 2px 2px; background-size: 2px 2px;
filter: drop-shadow(1px 1px 0px #777777); filter: drop-shadow(1px 1px 0px #777777);
} }
@ -133,7 +160,7 @@
padding: 0px; padding: 0px;
} }
.MobileApplicationWindow{ .MobileApplicationWindow {
width: 100%; width: 100%;
height: 100%; height: 100%;
/* Auto layout */ /* Auto layout */
@ -147,10 +174,10 @@
left: 0px; left: 0px;
} }
.MobileWindowFrameBottomBar{ .MobileWindowFrameBottomBar {
width: 100%; width: 100%;
height: 20px; height: 20px;
/* /*
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
@ -165,7 +192,7 @@
flex-grow: 0; flex-grow: 0;
} }
.MobileWindowFrameBottomBarButton{ .MobileWindowFrameBottomBarButton {
min-width: 11px; min-width: 11px;
width: auto; width: auto;
height: 15px; height: 15px;
@ -186,11 +213,11 @@
flex-grow: 0; flex-grow: 0;
} }
.MobileWindowFrameBottomBar .MobileLable{ .MobileWindowFrameBottomBar .MobileLable {
position: absolute; position: absolute;
/* top:1px; */ /* top:1px; */
/* font-size: 13px; */ /* font-size: 13px; */
left:50%; left: 50%;
pointer-events: none; pointer-events: none;
white-space: nowrap; white-space: nowrap;
@ -198,4 +225,3 @@
letter-spacing: 0.35px; letter-spacing: 0.35px;
} }

View File

@ -4,10 +4,13 @@
<head> <head>
<link rel="stylesheet" type="text/css" href="res/base.css"> <link rel="stylesheet" type="text/css" href="res/base.css">
<link rel="stylesheet" type="text/css" href="res/wdeUI.css"> <link rel="stylesheet" type="text/css" href="res/wdeUI.css">
<link rel="stylesheet" type="text/css" href="res/sys/wde/basic-widgets.css">
<link rel="stylesheet" type="text/css" href="res/sys/wde/wde-scrollbar.css"> <link rel="stylesheet" type="text/css" href="res/sys/wde/wde-scrollbar.css">
<link rel="stylesheet" type="text/css" href="res/sys/wde/basic-widgets.css">
<link rel="stylesheet" type="text/css" href="res/sys/wde/file-view.css"> <link rel="stylesheet" type="text/css" href="res/sys/wde/file-view.css">
<link rel="stylesheet" type="text/css" href="res/mobile-wdeUI.css"> <link rel="stylesheet" type="text/css" href="res/mobile-wdeUI.css">
<link rel="stylesheet" href="/res/sys/wde/simple-scrollbar.css"> <link rel="stylesheet" href="/res/sys/wde/simple-scrollbar.css">
<link rel="stylesheet" type="text/css" href="res/sys/finder/finder.css">
<link rel="stylesheet" href="/res/sys/personal-properties/personal-properies.css"> <link rel="stylesheet" href="/res/sys/personal-properties/personal-properies.css">
<link rel="stylesheet" href="/res/sys/img-viewer/img-viewer.css"> <link rel="stylesheet" href="/res/sys/img-viewer/img-viewer.css">
<link rel="stylesheet" href="/res/sys/blog-viewer/blog-viewer.css"> <link rel="stylesheet" href="/res/sys/blog-viewer/blog-viewer.css">

View File

@ -0,0 +1,28 @@
{{ define "finder/admin-app.tmpl" }}
<div class="TitleBar DragArea">
<button id="closeWindowButton" class="Button" title="Close Window"></button>
<div id="Drag" class="VisualDragArea"></div>
<div class="Lable">
Admin Finder
</div>
<div id="Drag" class="VisualDragArea"></div>
</div>
<div id="ContentBorder" class="ContentBorder AdjectiveElement">
<div class="FinderContent">
<div class="ToolBar ConvexElement">
<button id="BackButton">Back</button>
<button id="HomeButton">Home</button>
</div>
<div class="FinderFileView">
<div class="FileTileView">
</div>
{{template "wde-widgets/scrollbar.tmpl" .}}
</div>
</div>
</div>
{{ end }}

View File

@ -1,17 +1,19 @@
{{ define "finder/app.tmpl" }} {{ define "finder/app.tmpl" }}
<div class="TitleBar DragArea"> <div class="TitleBar DragArea">
<button id="closeWindowButton" class="Button" title="Close Window"></button> <button id="closeWindowButton" class="Button" title="Close Window"></button>
<div class="TitleBarTest">
<div id="Drag" class="VisualDragArea"></div> <div id="Drag" class="VisualDragArea"></div>
<div class="Lable"> <div class="Lable">
Files Files
</div> </div>
<div id="Drag" class="VisualDragArea"></div> <div id="Drag" class="VisualDragArea"></div>
</div> </div>
</div>
<div class="ToolBar"> <div class="ToolBar">
<button id="BackButton">Back</button> <button id="BackButton">Back</button>
<button id="HomeButton">Home</button> <button id="HomeButton">Home</button>
</div> </div>
<div class="ContentBorder"> <div class="ContentBorder ConvexElement">
<div class="FileTileView"> <div class="FileTileView">
</div> </div>

View File

@ -0,0 +1,28 @@
{{ define "wde-widgets/context-menu.tmpl" }}
<!-- <div class="ContextMenu WindowFrameShadow"> -->
<div class="MenuContent ConvexElement">
<div class="Row">
<div class="Lable NoClick">Open</div>
</div>
<div class="Row" actionType="" action="">
<div class="Lable NoClick">Test</div>
</div>
<div class="AdjectiveHorizontalLine"></div>
<div class="Row">
<div class="Lable NoClick">Lol kek</div>
</div>
<div class="Row">
<div class="Lable NoClick">Delete this file</div>
</div>
<div class="Row">
<div class="Lable NoClick">Save to computer</div>
</div>
<div class="Row">
<div class="Lable NoClick">Pizda</div>
</div>
<div class="Row">
<div class="Lable NoClick">Azaza</div>
</div>
</div>
<!-- </div> -->
{{ end }}

View File

@ -32,6 +32,17 @@ func (w *WDE) Render(path string) (gin.H, error) {
}, nil }, nil
} }
func (w *WDE) RenderContextMenu() (gin.H, error) {
// list, err := w.fs.List(path)
// if err != nil {
// return nil, err
// }
return gin.H{
"Name": "Greg Brzezinski",
// "Files": list,
}, nil
}
func (w *WDE) RenderFileTileView(directory string, host string) (gin.H, error) { func (w *WDE) RenderFileTileView(directory string, host string) (gin.H, error) {
list, err := w.fs.List(directory) list, err := w.fs.List(directory)
if err != nil { if err != nil {

View File

@ -3,8 +3,10 @@ package webfilesystem
import ( import (
"context" "context"
"errors" "errors"
"net/http"
"strings" "strings"
"github.com/gin-gonic/gin"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
@ -172,6 +174,76 @@ func (fs *WebFileSystem) GetParentPath(path string) string {
return parentPath return parentPath
} }
func (fs *WebFileSystem) Route(route *gin.RouterGroup) {
route.GET("writeFile", func(ctx *gin.Context) {
parentPath := ctx.Query("parentPath")
if parentPath == "" {
ctx.JSON(http.StatusBadRequest, "TODO") //TODO json error struct
return
}
file := WebFSFile{
MongoId: primitive.NewObjectID(),
Name: "pp",
Type: "test",
Data: nil,
}
err := fs.CreateFile(&file, parentPath)
if err != nil {
ctx.JSON(http.StatusInternalServerError, "TODO") //TODO json error struct
return
}
ctx.JSON(http.StatusOK, "OK")
})
route.GET("createDir", func(ctx *gin.Context) {
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "TODO") //TODO json error struct
return
}
err := fs.CreateDirectory(path)
if err != nil {
ctx.JSON(http.StatusInternalServerError, "TODO") //TODO json error struct
return
}
ctx.JSON(http.StatusOK, "OK")
})
route.GET("list", func(ctx *gin.Context) {
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "TODO") //TODO json error struct
return
}
files, err := fs.List(path)
if err != nil {
ctx.JSON(http.StatusInternalServerError, "TODO") //TODO json error struct
return
}
ctx.JSON(http.StatusOK, &files)
})
route.GET("read", func(ctx *gin.Context) {
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "TODO") //TODO json error struct
return
}
file, err := fs.Read(path)
if err != nil {
ctx.JSON(http.StatusInternalServerError, "TODO") //TODO json error struct
return
}
ctx.JSON(http.StatusOK, &file)
})
}
type WebFSFile struct { type WebFSFile struct {
MongoId primitive.ObjectID `bson:"_id" json:"-"` MongoId primitive.ObjectID `bson:"_id" json:"-"`
Name string `bson:"name" json:"name"` Name string `bson:"name" json:"name"`

View File

@ -1,34 +0,0 @@
package finder
import (
"personalwebsite/webfilesystem"
"personalwebsite/websiteapp"
"github.com/gin-gonic/gin"
)
type FinderApplication struct {
fs *webfilesystem.WebFileSystem
manifest websiteapp.ApplicationManifest
}
func NewFinderApplication(webFs *webfilesystem.WebFileSystem) *FinderApplication {
return &FinderApplication{
fs: webFs,
manifest: websiteapp.ApplicationManifest{
AppId: "finder",
WindowName: "TODO DELETE", //TODO DELETE
},
}
}
func (f *FinderApplication) GetManifest() websiteapp.ApplicationManifest {
return f.manifest
}
func (f *FinderApplication) GetId() string {
return f.manifest.AppId
}
func (f *FinderApplication) Render(isMobile bool) gin.H {
return gin.H{}
}