Compare commits
152 Commits
finder/ope
...
main
Author | SHA1 | Date | |
---|---|---|---|
264a8d38d6 | |||
38c1d03755 | |||
71d5e34e49 | |||
5ff8696ea4 | |||
74cb1ced32 | |||
e76c55f2c3 | |||
3b5b00f5b0 | |||
b79b65868c | |||
766b7ac4bf | |||
d1c5e8ea15 | |||
559c22f626 | |||
265f57e2de | |||
46e3bcf865 | |||
68664c1bf3 | |||
3636cb86e2 | |||
9f60c185ad | |||
ec9ef532f6 | |||
71431790b5 | |||
41bd2a43b8 | |||
bd0f77b1b6 | |||
bc71ca9682 | |||
c5c277f516 | |||
d018477fe3 | |||
d61fa2bd4b | |||
edf011fccd | |||
186ea27db8 | |||
cb1dfce2a9 | |||
0e9720d295 | |||
96f8be759e | |||
de0ad81615 | |||
488f3a56b9 | |||
fb6b310a49 | |||
86552cb22f | |||
2ba61f10ff | |||
b0c7b6a690 | |||
81af984d96 | |||
651e219b09 | |||
e6138cba1e | |||
a921646f4c | |||
c1ba99bb77 | |||
5aaea9c1be | |||
55bb4c17fc | |||
b975dd958a | |||
0599e35a92 | |||
641e58984b | |||
4cb31d2e19 | |||
9ec954ceb3 | |||
5d160bddd9 | |||
9cc2dc5a42 | |||
56038cc284 | |||
f363ebbe10 | |||
2a5f0bb3f4 | |||
6a93f418d5 | |||
d2ea95a182 | |||
1b3f17777e | |||
8facac5d19 | |||
435e98dac0 | |||
5b03a465fc | |||
08473aab11 | |||
6dc162f3ff | |||
3702495714 | |||
50d7924728 | |||
7f2c7f065c | |||
4426d30342 | |||
9c0cc8d709 | |||
f81e15f1b8 | |||
da8af8222d | |||
61cbf717c3 | |||
46ad190b2a | |||
ade7b9b021 | |||
5b0830de4d | |||
5fe693f664 | |||
5c6d1d65a6 | |||
c9e846e2cf | |||
113b7ebc37 | |||
ea65976d01 | |||
fa50328474 | |||
b5cde34178 | |||
b8eda48aa7 | |||
9b88db9289 | |||
0ceae10530 | |||
6c3bc32b59 | |||
1beba0f0ee | |||
405f45e788 | |||
c95501dbb7 | |||
5736b8de31 | |||
2197356dcc | |||
ccaebdc667 | |||
70a163c4aa | |||
71dc0c519b | |||
00750280df | |||
1e93568f9b | |||
ccc24b93ad | |||
b496ce2ab2 | |||
313be711a9 | |||
bea6859457 | |||
4382b57e9e | |||
2f3cb85d22 | |||
0b6507e52a | |||
8b7dac3c60 | |||
6bc3b0d79b | |||
e1635f5e27 | |||
809b7aa901 | |||
41ca6ba346 | |||
7fe9660923 | |||
be13dcd525 | |||
139831365a | |||
0ae5eb4325 | |||
7e65712103 | |||
70bcc60edd | |||
17dbd6249b | |||
93dcea8b21 | |||
624bd3255c | |||
c77dc479db | |||
8e2d014317 | |||
a0ccc5e120 | |||
0d1dcde727 | |||
3b8bc166cb | |||
d549c96492 | |||
6c5d804ae0 | |||
2f2ad23fd6 | |||
e9422f797b | |||
f736033ce3 | |||
4c0bea4f89 | |||
5f6d5e7a48 | |||
326e150780 | |||
5f07c9a52c | |||
0a8e438d4d | |||
06a87af35b | |||
471350ead1 | |||
b6b3cf9ca1 | |||
21b201fd9d | |||
8d424398dd | |||
38e4058840 | |||
58eabd1af9 | |||
e1e62a0373 | |||
451486f44b | |||
fdf2228c3e | |||
8701baab7a | |||
c1bed6e2cd | |||
10a7cf9301 | |||
6ef9ac2df1 | |||
eaa3ce9d5d | |||
9478c6c8dd | |||
dc7bf44576 | |||
8cb9b62b9d | |||
c4d3eae21a | |||
0f7ef6cd31 | |||
44748f8070 | |||
6949d77584 | |||
7776c82ca1 | |||
4da2a3e556 |
8
.gitignore
vendored
8
.gitignore
vendored
@ -22,3 +22,11 @@
|
|||||||
go.work
|
go.work
|
||||||
|
|
||||||
/__debug_bin
|
/__debug_bin
|
||||||
|
.env
|
||||||
|
|
||||||
|
front/dist/*
|
||||||
|
|
||||||
|
front/node_modules
|
||||||
|
.parcel-cache
|
||||||
|
**/node_modules/
|
||||||
|
front/node_modules/*
|
@ -10,7 +10,7 @@ FROM golang:1.18-alpine
|
|||||||
WORKDIR /usr/app
|
WORKDIR /usr/app
|
||||||
COPY --from=build /usr/app/personalwebsite /usr/app/personalwebsite
|
COPY --from=build /usr/app/personalwebsite /usr/app/personalwebsite
|
||||||
COPY ./templates /usr/app/templates
|
COPY ./templates /usr/app/templates
|
||||||
COPY ./resources /usr/app/resources
|
COPY ./res /usr/app/res
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
|
37
apps/BlogWriter/blogwriter.go
Normal file
37
apps/BlogWriter/blogwriter.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package blogwriter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"personalwebsite/apps"
|
||||||
|
"personalwebsite/webfilesystem"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BlogWriterApplication struct {
|
||||||
|
fs *webfilesystem.WebFileSystem
|
||||||
|
appID string
|
||||||
|
path string
|
||||||
|
manifest apps.ApplicationManifest
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBlogWriterApp(webfs *webfilesystem.WebFileSystem) *BlogWriterApplication {
|
||||||
|
return &BlogWriterApplication{
|
||||||
|
fs: webfs,
|
||||||
|
appID: "BlogWriter",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (bw *BlogWriterApplication) GetManifest() apps.ApplicationManifest {
|
||||||
|
return bw.manifest
|
||||||
|
}
|
||||||
|
func (bw *BlogWriterApplication) GetAppID() string {
|
||||||
|
return bw.appID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bw *BlogWriterApplication) GetPath() string {
|
||||||
|
return bw.path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bw *BlogWriterApplication) PublicRoutes(routes *gin.RouterGroup) {}
|
||||||
|
func (bw *BlogWriterApplication) PrivateRoutes(routes *gin.RouterGroup) {
|
||||||
|
|
||||||
|
}
|
335
apps/aboutme/personalprops.go
Normal file
335
apps/aboutme/personalprops.go
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
package aboutme
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"html/template"
|
||||||
|
"net/http"
|
||||||
|
"path"
|
||||||
|
"personalwebsite/apps"
|
||||||
|
"personalwebsite/apps/appCtx"
|
||||||
|
"personalwebsite/errormessage"
|
||||||
|
"personalwebsite/libs"
|
||||||
|
"personalwebsite/wde"
|
||||||
|
"personalwebsite/webfilesystem"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AboutMeApp struct {
|
||||||
|
fs *webfilesystem.WebFileSystem
|
||||||
|
appID string
|
||||||
|
mLib libs.MarkdownLib
|
||||||
|
titleBarConfig wde.TitleBarConfig //TODO to app manifest?
|
||||||
|
path string
|
||||||
|
manifest apps.ApplicationManifest
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAboutMeApp(webFs *webfilesystem.WebFileSystem) *AboutMeApp {
|
||||||
|
manifest := apps.ApplicationManifest{}
|
||||||
|
_, err := webFs.Read(path.Join("/Applications/AboutMe.app", ".appmanifest"), &manifest)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
newApp := AboutMeApp{
|
||||||
|
fs: webFs,
|
||||||
|
appID: "AboutMe",
|
||||||
|
path: "/Applications/AboutMe.app",
|
||||||
|
titleBarConfig: wde.TitleBarConfig{
|
||||||
|
Lable: "About Me",
|
||||||
|
CloseButton: true,
|
||||||
|
HasIcon: true,
|
||||||
|
IconPath: "/Icons/GenericApp.icn",
|
||||||
|
IconSize: "16",
|
||||||
|
},
|
||||||
|
manifest: manifest,
|
||||||
|
}
|
||||||
|
return &newApp
|
||||||
|
}
|
||||||
|
func (p *AboutMeApp) GetPath() string {
|
||||||
|
return p.path
|
||||||
|
}
|
||||||
|
func (p *AboutMeApp) GetManifest() apps.ApplicationManifest {
|
||||||
|
return p.manifest
|
||||||
|
}
|
||||||
|
func (p *AboutMeApp) PublicRoutes(route *gin.RouterGroup) {
|
||||||
|
route.POST("render", func(ctx *gin.Context) {
|
||||||
|
filePath := ctx.Query("path")
|
||||||
|
if filePath == "" {
|
||||||
|
ctx.Status(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
appCtx := appCtx.AppContext{}
|
||||||
|
err := ctx.BindJSON(&appCtx)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Status(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ginH, err := p.Render(appCtx, filePath)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, "TODO") //TODO
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if appCtx.IsMobile {
|
||||||
|
ctx.HTML(http.StatusOK, "personal-properties/mobile-app.tmpl", ginH)
|
||||||
|
} else {
|
||||||
|
ctx.HTML(http.StatusOK, "personal-properties/app.tmpl", ginH)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AboutMeApp) PrivateRoutes(router *gin.RouterGroup) {
|
||||||
|
p.PublicRoutes(router)
|
||||||
|
router.GET("writeMock", func(ctx *gin.Context) {
|
||||||
|
err := p.WriteMock()
|
||||||
|
if err != nil {
|
||||||
|
ctx.Status(http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
ctx.Status(http.StatusOK)
|
||||||
|
})
|
||||||
|
|
||||||
|
router.GET("getMock", func(ctx *gin.Context) {
|
||||||
|
ctx.JSON(http.StatusOK, PropertiesFileData{
|
||||||
|
Header: HeaderIsland{
|
||||||
|
Name: "",
|
||||||
|
IconPath: "",
|
||||||
|
Value1: "",
|
||||||
|
Value2: "",
|
||||||
|
},
|
||||||
|
Links: []HeaderLink{
|
||||||
|
{
|
||||||
|
Text: "",
|
||||||
|
Url: "",
|
||||||
|
Icon: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Islands: []Island{
|
||||||
|
{
|
||||||
|
Header: "qq",
|
||||||
|
Properties: []IslandProperty{
|
||||||
|
{
|
||||||
|
Key: "22",
|
||||||
|
KeyComments: []string{
|
||||||
|
"45",
|
||||||
|
"12",
|
||||||
|
},
|
||||||
|
Values: []string{
|
||||||
|
"aaaa",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
router.GET("read", func(ctx *gin.Context) {
|
||||||
|
filePath := ctx.Query("path")
|
||||||
|
if filePath == "" {
|
||||||
|
ctx.JSON(http.StatusBadRequest, errormessage.ErrorMessage{
|
||||||
|
Message: "File path is empty",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
propData, err := p.Read(filePath)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, errormessage.ErrorMessage{
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusOK, propData)
|
||||||
|
})
|
||||||
|
|
||||||
|
router.POST("edit", func(ctx *gin.Context) {
|
||||||
|
filePath := ctx.Query("path")
|
||||||
|
if filePath == "" {
|
||||||
|
ctx.JSON(http.StatusBadRequest, errormessage.ErrorMessage{
|
||||||
|
Message: "File path is empty",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
propsData := PropertiesFileData{}
|
||||||
|
err := ctx.BindJSON(&propsData)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusBadRequest, errormessage.ErrorMessage{
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = p.Edit(filePath, propsData)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, errormessage.ErrorMessage{
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Status(http.StatusOK)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AboutMeApp) GetAppID() string {
|
||||||
|
return p.appID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AboutMeApp) WriteMock() error {
|
||||||
|
fileHeader := webfilesystem.FileHeader{
|
||||||
|
MongoId: primitive.NewObjectID(),
|
||||||
|
Name: "aboutme.props",
|
||||||
|
Type: "personal-properties",
|
||||||
|
Icon: "",
|
||||||
|
}
|
||||||
|
fileData := PropertiesFileData{
|
||||||
|
Header: HeaderIsland{
|
||||||
|
Name: "Test Name",
|
||||||
|
IconPath: "test icon path",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, _, err := p.fs.Write("/Applications/AboutMe.app/aboutme.props", &fileHeader, fileData)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AboutMeApp) Read(filePath string) (*PropertiesFileData, error) {
|
||||||
|
propData := PropertiesFileData{}
|
||||||
|
fileHeader, err := p.fs.Read(path.Join(filePath, "aboutme.props"), &propData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if fileHeader.Type != "personal-properties" {
|
||||||
|
return nil, errors.New("wrong file type")
|
||||||
|
}
|
||||||
|
return &propData, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AboutMeApp) Edit(filePath string, blogData PropertiesFileData) error {
|
||||||
|
propsPath := path.Join(filePath, "aboutme.props")
|
||||||
|
fileHeader, err := p.fs.Read(propsPath, nil)
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() == "file not found" { //FIXME
|
||||||
|
p.WriteMock()
|
||||||
|
p.Edit(filePath, blogData)
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if fileHeader.Type != "personal-properties" {
|
||||||
|
return errors.New("wrong file type")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = p.fs.Remove(propsPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fileHeader.MongoId = primitive.NewObjectID()
|
||||||
|
_, _, err = p.fs.Write(propsPath, fileHeader, blogData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AboutMeApp) Render(appCtx appCtx.AppContext, filePath string) (gin.H, error) {
|
||||||
|
//Read file from WebFS
|
||||||
|
propsData := &PropertiesFileData{}
|
||||||
|
filePath = p.fs.RelativeToAbsolute(appCtx, filePath)
|
||||||
|
_, err := p.fs.Read(filePath, &propsData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//Render Markdown strings
|
||||||
|
renderedIslands := []RenderedIsland{}
|
||||||
|
for _, island := range propsData.Islands {
|
||||||
|
newRenderedIsland := RenderedIsland{
|
||||||
|
Header: island.Header,
|
||||||
|
Properties: []RenderedIslandProperty{},
|
||||||
|
}
|
||||||
|
for _, property := range island.Properties {
|
||||||
|
newRenderedIslandProperty := RenderedIslandProperty{
|
||||||
|
Key: property.Key,
|
||||||
|
KeyComments: property.KeyComments,
|
||||||
|
Values: []template.HTML{},
|
||||||
|
}
|
||||||
|
for _, value := range property.Values {
|
||||||
|
renderedValue := p.mLib.Render([]byte(value), true)
|
||||||
|
newRenderedIslandProperty.Values = append(newRenderedIslandProperty.Values, renderedValue)
|
||||||
|
}
|
||||||
|
newRenderedIsland.Properties = append(newRenderedIsland.Properties, newRenderedIslandProperty)
|
||||||
|
}
|
||||||
|
renderedIslands = append(renderedIslands, newRenderedIsland)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Make icon path absolute
|
||||||
|
propsData.Header.IconPath = p.fs.RelativeToAbsolute(appCtx, propsData.Header.IconPath)
|
||||||
|
|
||||||
|
absoluteLinks := []HeaderLink{}
|
||||||
|
for _, link := range propsData.Links {
|
||||||
|
absoluteLinks = append(absoluteLinks, HeaderLink{
|
||||||
|
Text: link.Text,
|
||||||
|
Url: link.Url,
|
||||||
|
Icon: p.fs.RelativeToAbsolute(appCtx, link.Icon),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return gin.H{
|
||||||
|
"TitleBarConfig": p.titleBarConfig,
|
||||||
|
"HeaderProps": propsData.Header,
|
||||||
|
"Links": absoluteLinks,
|
||||||
|
"Islands": renderedIslands,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type PropertiesFileData struct {
|
||||||
|
Header HeaderIsland `bson:"header" json:"header"`
|
||||||
|
Links []HeaderLink `bson:"links" json:"links"`
|
||||||
|
Islands []Island `bson:"islands" json:"islands"` //TODO rename
|
||||||
|
}
|
||||||
|
|
||||||
|
type HeaderIsland struct {
|
||||||
|
Name string `bson:"name" json:"name"`
|
||||||
|
IconPath string `bson:"iconpath" json:"iconpath"`
|
||||||
|
Value1 string `bson:"value1" json:"value1"` //TODO Rename to value
|
||||||
|
Value2 string `bson:"value2" json:"value2"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type HeaderLink struct {
|
||||||
|
Text string `bson:"text" json:"text"`
|
||||||
|
Url string `bson:"url" json:"url"`
|
||||||
|
Icon string `bson:"icon" json:"icon"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Island struct {
|
||||||
|
Header string `bson:"header" json:"header"`
|
||||||
|
Properties []IslandProperty `bson:"properties" json:"properties"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IslandProperty struct {
|
||||||
|
Key string `bson:"key" json:"key"`
|
||||||
|
KeyComments []string `bson:"keycomment" json:"keycomment"`
|
||||||
|
Values []string `bson:"values" json:"values"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RenderedIsland struct {
|
||||||
|
Header string
|
||||||
|
Properties []RenderedIslandProperty
|
||||||
|
}
|
||||||
|
|
||||||
|
type RenderedIslandProperty struct {
|
||||||
|
Key string
|
||||||
|
KeyComments []string
|
||||||
|
Values []template.HTML
|
||||||
|
}
|
||||||
|
|
||||||
|
// type Value struct {
|
||||||
|
// Blocks []ValueBlock
|
||||||
|
// }
|
||||||
|
|
||||||
|
// type ValueBlock struct {
|
||||||
|
// Type string
|
||||||
|
// Data string
|
||||||
|
// }
|
8
apps/appCtx/appContext.go
Normal file
8
apps/appCtx/appContext.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package appCtx
|
||||||
|
|
||||||
|
//TODO to websiteapp package
|
||||||
|
type AppContext struct {
|
||||||
|
IsMobile bool `json:"isMobile"`
|
||||||
|
BundlePath string `json:"bundlePath"`
|
||||||
|
RunPath string `json:"runPath"`
|
||||||
|
}
|
18
apps/blogviewer/blogfile.go
Normal file
18
apps/blogviewer/blogfile.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package blogviewer
|
||||||
|
|
||||||
|
import "html/template"
|
||||||
|
|
||||||
|
type BlogFileData struct {
|
||||||
|
Header string `bson:"header"`
|
||||||
|
Blocks []*Block `bson:"blocks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Block struct {
|
||||||
|
Type string `bson:"type"`
|
||||||
|
Data []string `bson:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RenderedBlock struct {
|
||||||
|
Type string `bson:"type"`
|
||||||
|
Data []template.HTML `bson:"data"`
|
||||||
|
}
|
266
apps/blogviewer/blogviewer.go
Normal file
266
apps/blogviewer/blogviewer.go
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
package blogviewer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"path"
|
||||||
|
"personalwebsite/apps"
|
||||||
|
"personalwebsite/apps/appCtx"
|
||||||
|
"personalwebsite/errormessage"
|
||||||
|
"personalwebsite/libs"
|
||||||
|
"personalwebsite/webfilesystem"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BlogViewerApplication struct {
|
||||||
|
fs *webfilesystem.WebFileSystem
|
||||||
|
appID string
|
||||||
|
mLib libs.MarkdownLib
|
||||||
|
path string
|
||||||
|
manifest apps.ApplicationManifest
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBlogViewerApp(webFs *webfilesystem.WebFileSystem) *BlogViewerApplication {
|
||||||
|
return &BlogViewerApplication{
|
||||||
|
fs: webFs,
|
||||||
|
appID: "BlogViewer",
|
||||||
|
mLib: libs.MarkdownLib{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (b *BlogViewerApplication) GetManifest() apps.ApplicationManifest {
|
||||||
|
return b.manifest
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BlogViewerApplication) GetAppID() string {
|
||||||
|
return b.appID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BlogViewerApplication) GetPath() string {
|
||||||
|
return b.path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BlogViewerApplication) PrivateRoutes(route *gin.RouterGroup) {
|
||||||
|
b.PublicRoutes(route)
|
||||||
|
|
||||||
|
route.POST("test", func(ctx *gin.Context) {
|
||||||
|
blogData := BlogFileData{}
|
||||||
|
err := ctx.BindJSON(&blogData)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Status(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mLib := libs.MarkdownLib{}
|
||||||
|
for _, block := range blogData.Blocks {
|
||||||
|
for _, str := range block.Data {
|
||||||
|
test := []byte(str)
|
||||||
|
mLib.Render(test, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
route.GET("writeMockBlog", func(ctx *gin.Context) {
|
||||||
|
path := ctx.Query("path")
|
||||||
|
if path == "" {
|
||||||
|
ctx.JSON(http.StatusBadRequest, "no path provided")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := b.WriteMock(path)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Status(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.JSON(http.StatusOK, "OK")
|
||||||
|
})
|
||||||
|
|
||||||
|
route.POST("edit", func(ctx *gin.Context) {
|
||||||
|
filePath := ctx.Query("path")
|
||||||
|
if filePath == "" {
|
||||||
|
ctx.JSON(http.StatusBadRequest, errormessage.ErrorMessage{
|
||||||
|
Message: "File path is empty",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
blogData := BlogFileData{}
|
||||||
|
err := ctx.BindJSON(&blogData)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Status(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = b.Edit(filePath, blogData)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, errormessage.ErrorMessage{
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Status(http.StatusOK)
|
||||||
|
})
|
||||||
|
|
||||||
|
route.GET("read", func(ctx *gin.Context) {
|
||||||
|
filePath := ctx.Query("path")
|
||||||
|
if filePath == "" {
|
||||||
|
ctx.JSON(http.StatusBadRequest, errormessage.ErrorMessage{
|
||||||
|
Message: "File path is empty",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
blogData, err := b.Read(filePath)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, errormessage.ErrorMessage{
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.JSON(http.StatusOK, blogData)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BlogViewerApplication) PublicRoutes(route *gin.RouterGroup) {
|
||||||
|
|
||||||
|
route.POST("render", func(ctx *gin.Context) {
|
||||||
|
path := ctx.Query("path")
|
||||||
|
if path == "" {
|
||||||
|
ctx.JSON(http.StatusBadRequest, "no path provided")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
appCtx := appCtx.AppContext{}
|
||||||
|
err := ctx.BindJSON(&appCtx)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Status(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ginH, err := b.Render(path, appCtx)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, "TODO")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if appCtx.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) error {
|
||||||
|
blogFileHeader := webfilesystem.FileHeader{ //TODO to fs.CreateDirectory()
|
||||||
|
MongoId: primitive.NewObjectID(),
|
||||||
|
Name: "blog1.blog",
|
||||||
|
Type: "directory",
|
||||||
|
Icon: "",
|
||||||
|
Data: [12]byte{},
|
||||||
|
}
|
||||||
|
blogFileData := webfilesystem.DirectoryData{
|
||||||
|
MongoId: primitive.NewObjectID(),
|
||||||
|
Parent: [12]byte{},
|
||||||
|
Children: []primitive.ObjectID{},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err := b.fs.Write("/home/user/blog1.blog", &blogFileHeader, blogFileData)
|
||||||
|
if err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
blogContentFileHeader := webfilesystem.FileHeader{
|
||||||
|
MongoId: primitive.NewObjectID(),
|
||||||
|
Name: ".content",
|
||||||
|
Type: "blog-content",
|
||||||
|
Icon: "",
|
||||||
|
Data: [12]byte{},
|
||||||
|
}
|
||||||
|
blogContentFileData := BlogFileData{
|
||||||
|
Header: "OMG THIS IS BLOG",
|
||||||
|
}
|
||||||
|
blogContentFileData.Blocks = append(blogContentFileData.Blocks, &Block{
|
||||||
|
Type: "plain-text",
|
||||||
|
Data: []string{
|
||||||
|
"Apoqiwepoqiwepo",
|
||||||
|
".,mas;dakls;d",
|
||||||
|
"q[poqwieqpipoi]",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
_, _, err = b.fs.Write("/home/user/blog1.blog/.content", &blogContentFileHeader, blogContentFileData)
|
||||||
|
if err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BlogViewerApplication) Read(filePath string) (*BlogFileData, error) {
|
||||||
|
fileData := BlogFileData{}
|
||||||
|
fileHeader, err := b.fs.Read(path.Join(filePath, ".content"), &fileData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if fileHeader.Type != "blog-content" {
|
||||||
|
return nil, errors.New("wrong file type")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &fileData, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BlogViewerApplication) Edit(filePath string, blogData BlogFileData) error {
|
||||||
|
contentPath := path.Join(filePath, ".content")
|
||||||
|
fileHeader, err := b.fs.Read(contentPath, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if fileHeader.Type != "blog-content" {
|
||||||
|
return errors.New("wrong file type")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = b.fs.Remove(contentPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fileHeader.MongoId = primitive.NewObjectID()
|
||||||
|
_, _, err = b.fs.Write(contentPath, fileHeader, blogData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BlogViewerApplication) Render(filePath string, appCtx appCtx.AppContext) (gin.H, error) {
|
||||||
|
data := &BlogFileData{}
|
||||||
|
_, err := b.fs.Read(path.Join(filePath, ".content"), &data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newData := []RenderedBlock{}
|
||||||
|
for _, block := range data.Blocks {
|
||||||
|
newBlock := RenderedBlock{}
|
||||||
|
switch block.Type {
|
||||||
|
case "image":
|
||||||
|
// for _, image := range block.Data {
|
||||||
|
// newData = append(newData, b.fs.RelativeToAbsolute(appCtx, image))
|
||||||
|
// }
|
||||||
|
case "markdown":
|
||||||
|
for _, data := range block.Data {
|
||||||
|
renderedMD := b.mLib.Render([]byte(data), true)
|
||||||
|
newBlock.Data = append(newBlock.Data, renderedMD)
|
||||||
|
}
|
||||||
|
newData = append(newData, newBlock)
|
||||||
|
}
|
||||||
|
// block.Data = newData
|
||||||
|
}
|
||||||
|
|
||||||
|
return gin.H{
|
||||||
|
"header": data.Header,
|
||||||
|
"blocks": newData,
|
||||||
|
// "html": html,
|
||||||
|
}, nil
|
||||||
|
}
|
91
apps/finder/finder.go
Normal file
91
apps/finder/finder.go
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package finder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path"
|
||||||
|
"personalwebsite/apps"
|
||||||
|
"personalwebsite/apps/appCtx"
|
||||||
|
"personalwebsite/wde"
|
||||||
|
"personalwebsite/webfilesystem"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FinderApplication struct {
|
||||||
|
fs *webfilesystem.WebFileSystem
|
||||||
|
appID string
|
||||||
|
titleBarConfig wde.TitleBarConfig
|
||||||
|
path string
|
||||||
|
manifest apps.ApplicationManifest
|
||||||
|
// manifest apps.ApplicationManifest
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFinderApplication(webFs *webfilesystem.WebFileSystem) *FinderApplication {
|
||||||
|
manifest := apps.ApplicationManifest{}
|
||||||
|
_, err := webFs.Read(path.Join("/Applications/Finder.app", ".appmanifest"), &manifest)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return &FinderApplication{
|
||||||
|
fs: webFs,
|
||||||
|
path: "/Applications/Finder.app",
|
||||||
|
appID: "Finder",
|
||||||
|
titleBarConfig: wde.TitleBarConfig{
|
||||||
|
Lable: "Finder",
|
||||||
|
CloseButton: true,
|
||||||
|
HasIcon: true,
|
||||||
|
IconPath: "/Icons/GenericFolder.icn",
|
||||||
|
IconSize: "16",
|
||||||
|
},
|
||||||
|
manifest: manifest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (f *FinderApplication) GetManifest() apps.ApplicationManifest {
|
||||||
|
return f.manifest
|
||||||
|
}
|
||||||
|
func (f *FinderApplication) GetAppID() string {
|
||||||
|
return f.appID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FinderApplication) GetPath() string {
|
||||||
|
return f.path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FinderApplication) Render(appCtx appCtx.AppContext) gin.H {
|
||||||
|
return gin.H{
|
||||||
|
"TitleBarConfig": f.titleBarConfig,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FinderApplication) RenderPublicContextMenu(context string, filePath string, data string) gin.H {
|
||||||
|
islands := [][]wde.ContexMenuRow{}
|
||||||
|
islands = append(islands, []wde.ContexMenuRow{})
|
||||||
|
|
||||||
|
//TODO: Links read as source files in props info
|
||||||
|
islands = append(islands, []wde.ContexMenuRow{
|
||||||
|
{Label: "Get Info", Action: "getInfo"},
|
||||||
|
})
|
||||||
|
if context == "FileTileView" {
|
||||||
|
return gin.H{
|
||||||
|
"Islands": islands,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch context {
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
return gin.H{
|
||||||
|
"Islands": islands,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FinderApplication) RenderProps(filePath string) (gin.H, error) {
|
||||||
|
fileHeader, err := f.fs.Read(filePath, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gin.H{
|
||||||
|
"file": fileHeader,
|
||||||
|
}, nil
|
||||||
|
}
|
61
apps/finder/finderadmin.go
Normal file
61
apps/finder/finderadmin.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package finder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"personalwebsite/apps/appCtx"
|
||||||
|
"personalwebsite/wde"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (f *FinderApplication) RenderAdminWindow(appCtx appCtx.AppContext) gin.H {
|
||||||
|
|
||||||
|
return gin.H{}
|
||||||
|
}
|
||||||
|
func (f *FinderApplication) RenderPrivateContextMenu(context string, filePath string, data string) gin.H {
|
||||||
|
islands := [][]wde.ContexMenuRow{}
|
||||||
|
// islands = append(islands, []wde.ContexMenuRow{})
|
||||||
|
|
||||||
|
islands = append(islands, []wde.ContexMenuRow{
|
||||||
|
{Label: "Get Info", Action: "getInfo"},
|
||||||
|
})
|
||||||
|
|
||||||
|
if context == "FileTileView" {
|
||||||
|
islands = append(islands, []wde.ContexMenuRow{
|
||||||
|
{Label: "New Directory", Action: "createDir"},
|
||||||
|
})
|
||||||
|
return gin.H{
|
||||||
|
"Islands": islands,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
islands = append(islands, []wde.ContexMenuRow{
|
||||||
|
{Label: "Create path link", Action: "createPathLink"},
|
||||||
|
})
|
||||||
|
|
||||||
|
switch context {
|
||||||
|
case "directory":
|
||||||
|
switch f.fs.GetExtension(filePath) {
|
||||||
|
case "app":
|
||||||
|
islands = append(islands, []wde.ContexMenuRow{
|
||||||
|
{Label: "Open as Directory", Action: "openAsDir"},
|
||||||
|
})
|
||||||
|
case "blog":
|
||||||
|
islands = append(islands, []wde.ContexMenuRow{
|
||||||
|
{Label: "Open as Directory", Action: "openAsDir"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
islands = append(islands, []wde.ContexMenuRow{
|
||||||
|
{Label: "temp Menu 1", Action: ""},
|
||||||
|
{Label: "temp Menu 2", Action: ""},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
islands = append(islands, []wde.ContexMenuRow{
|
||||||
|
{Label: "Delete File", Action: "deleteFile"},
|
||||||
|
})
|
||||||
|
|
||||||
|
return gin.H{
|
||||||
|
"Islands": islands,
|
||||||
|
}
|
||||||
|
}
|
122
apps/finder/routes.go
Normal file
122
apps/finder/routes.go
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
package finder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"personalwebsite/apps/appCtx"
|
||||||
|
"personalwebsite/errormessage"
|
||||||
|
|
||||||
|
mobile "github.com/floresj/go-contrib-mobile"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (f *FinderApplication) PublicRoutes(routes *gin.RouterGroup) {
|
||||||
|
routes.POST("render", func(ctx *gin.Context) {
|
||||||
|
appCtx := appCtx.AppContext{}
|
||||||
|
err := ctx.BindJSON(&appCtx)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusBadRequest, errormessage.ErrorMessage{
|
||||||
|
Message: "Error in decoding app bundle",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d := mobile.GetDevice(ctx)
|
||||||
|
switch {
|
||||||
|
case d.Mobile():
|
||||||
|
ctx.HTML(http.StatusOK, "templates/finder/mobile-app.tmpl", gin.H{
|
||||||
|
// "autostart": autostart,
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
ctx.HTML(http.StatusOK, "finder/app.tmpl", f.Render(appCtx))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
//Obsolete
|
||||||
|
routes.GET("renderMobileDesktop", func(ctx *gin.Context) {
|
||||||
|
ctx.HTML(http.StatusOK, "finder/mobile-desktop.tmpl", gin.H{})
|
||||||
|
})
|
||||||
|
|
||||||
|
routes.POST("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) {
|
||||||
|
context := ctx.Query("context")
|
||||||
|
filePath := ctx.Query("path")
|
||||||
|
if filePath == "" {
|
||||||
|
ctx.Status(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data := ctx.Query("data")
|
||||||
|
ginH := f.RenderPublicContextMenu(context, filePath, data)
|
||||||
|
ctx.HTML(http.StatusOK, "wde-widgets/context-menu.tmpl", ginH)
|
||||||
|
})
|
||||||
|
|
||||||
|
routes.GET("renderProps", func(ctx *gin.Context) {
|
||||||
|
filePath := ctx.Query("path")
|
||||||
|
ginH, err := f.RenderProps(filePath)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Status(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.HTML(http.StatusOK, "finder/props.tmpl", ginH)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FinderApplication) PrivateRoutes(routes *gin.RouterGroup) {
|
||||||
|
routes.POST("render", func(ctx *gin.Context) {
|
||||||
|
appCtx := appCtx.AppContext{}
|
||||||
|
err := ctx.BindJSON(&appCtx)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusBadRequest, errormessage.ErrorMessage{
|
||||||
|
Message: "Error in decoding app bundle",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d := mobile.GetDevice(ctx)
|
||||||
|
switch {
|
||||||
|
case d.Mobile():
|
||||||
|
ctx.HTML(http.StatusOK, "finder/mobile-app.tmpl", f.Render(appCtx))
|
||||||
|
default:
|
||||||
|
ctx.HTML(http.StatusOK, "finder/admin-app.tmpl", f.Render(appCtx))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
routes.GET("renderMobileDesktop", func(ctx *gin.Context) {
|
||||||
|
ctx.HTML(http.StatusOK, "finder/mobile-desktop.tmpl", gin.H{})
|
||||||
|
})
|
||||||
|
routes.POST("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) {
|
||||||
|
context := ctx.Query("context")
|
||||||
|
filePath := ctx.Query("path")
|
||||||
|
if filePath == "" {
|
||||||
|
ctx.Status(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data := ctx.Query("data")
|
||||||
|
ginH := f.RenderPrivateContextMenu(context, filePath, data)
|
||||||
|
ctx.HTML(http.StatusOK, "wde-widgets/context-menu.tmpl", ginH)
|
||||||
|
})
|
||||||
|
|
||||||
|
routes.GET("renderProps", func(ctx *gin.Context) {
|
||||||
|
filePath := ctx.Query("path")
|
||||||
|
ginH, err := f.RenderProps(filePath)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Status(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.HTML(http.StatusOK, "finder/props.tmpl", ginH)
|
||||||
|
})
|
||||||
|
}
|
82
apps/img-viewer/imgviewer.go
Normal file
82
apps/img-viewer/imgviewer.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package imgviewer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"personalwebsite/apps"
|
||||||
|
"personalwebsite/webfilesystem"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ImgViewerApp struct {
|
||||||
|
fs *webfilesystem.WebFileSystem
|
||||||
|
appID string
|
||||||
|
path string
|
||||||
|
manifest apps.ApplicationManifest
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewImgViewerApp(webFs *webfilesystem.WebFileSystem) *ImgViewerApp {
|
||||||
|
newApp := ImgViewerApp{
|
||||||
|
fs: webFs,
|
||||||
|
appID: "ImgViewer",
|
||||||
|
}
|
||||||
|
return &newApp
|
||||||
|
}
|
||||||
|
func (p *ImgViewerApp) PrivateRoutes(route *gin.RouterGroup) {
|
||||||
|
p.PublicRoutes(route)
|
||||||
|
}
|
||||||
|
func (i *ImgViewerApp) GetManifest() apps.ApplicationManifest {
|
||||||
|
return i.manifest
|
||||||
|
}
|
||||||
|
func (p *ImgViewerApp) PublicRoutes(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) GetPath() string {
|
||||||
|
return p.path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ImgViewerApp) GetAppID() string {
|
||||||
|
return p.appID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ImgViewerApp) Render(filePath string, isMobile bool) (gin.H, error) {
|
||||||
|
// file, err := p.fs.NewRead(filePath)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
// println(file.Data.(primitive.Binary).Data)
|
||||||
|
|
||||||
|
// img, err := p.fs.NewRead(path)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
// data, err := libs.ReadImage(img)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
// url := location.Get(ctx)
|
||||||
|
return gin.H{
|
||||||
|
"imgUrl": "/system/libs/img/get?path=" + filePath,
|
||||||
|
// "header": data.Header,
|
||||||
|
// "base64": data.Base64,
|
||||||
|
}, nil
|
||||||
|
}
|
86
apps/sunboard/sunboard.go
Normal file
86
apps/sunboard/sunboard.go
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package sunboard
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"path"
|
||||||
|
"personalwebsite/apps"
|
||||||
|
"personalwebsite/wde"
|
||||||
|
"personalwebsite/webfilesystem"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SunboardApp struct {
|
||||||
|
fs *webfilesystem.WebFileSystem
|
||||||
|
wde *wde.WDE
|
||||||
|
appID string
|
||||||
|
appStorage *apps.ApplicationsStorage
|
||||||
|
path string
|
||||||
|
manifest apps.ApplicationManifest
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSunboardApp(webFs *webfilesystem.WebFileSystem, wde *wde.WDE, appStorage *apps.ApplicationsStorage) *SunboardApp {
|
||||||
|
manifest := apps.ApplicationManifest{}
|
||||||
|
_, err := webFs.Read(path.Join("/Applications/Sunboard.app", ".appmanifest"), &manifest)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
newApp := SunboardApp{
|
||||||
|
fs: webFs,
|
||||||
|
wde: wde,
|
||||||
|
appID: "Sunboard",
|
||||||
|
appStorage: appStorage,
|
||||||
|
path: "/Applications/Sunboard.app",
|
||||||
|
manifest: manifest,
|
||||||
|
}
|
||||||
|
return &newApp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *SunboardApp) GetAppID() string {
|
||||||
|
return a.appID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *SunboardApp) PublicRoutes(route *gin.RouterGroup) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *SunboardApp) GetPath() string {
|
||||||
|
return a.path
|
||||||
|
}
|
||||||
|
func (a *SunboardApp) GetManifest() apps.ApplicationManifest {
|
||||||
|
return a.manifest
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *SunboardApp) PrivateRoutes(router *gin.RouterGroup) {
|
||||||
|
router.POST("render", func(ctx *gin.Context) {
|
||||||
|
appIcons := []appIcon{}
|
||||||
|
for _, app := range a.appStorage.Apps {
|
||||||
|
if app.GetAppID() == "Sunboard" { //FIXME
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if app.GetManifest().Iconpath == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
println(app.GetAppID() + " : " + app.GetPath())
|
||||||
|
// iconPath := path.Join(, "icon.icn")
|
||||||
|
appIcons = append(appIcons, appIcon{
|
||||||
|
Type: "Icon",
|
||||||
|
Icon: "/system/libs/img/icon/get?path=" + app.GetManifest().Iconpath + "&size=32",
|
||||||
|
Lable: app.GetAppID(),
|
||||||
|
AppId: app.GetAppID(),
|
||||||
|
Path: app.GetPath(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ctx.HTML(http.StatusOK, "sunboard/sunboard.html", gin.H{
|
||||||
|
"AppsIcons": appIcons,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type appIcon struct {
|
||||||
|
AppId string
|
||||||
|
Type string
|
||||||
|
Icon string
|
||||||
|
Lable string
|
||||||
|
Path string
|
||||||
|
}
|
145
apps/websiteapp.go
Normal file
145
apps/websiteapp.go
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package apps
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"path"
|
||||||
|
"personalwebsite/webfilesystem"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
)
|
||||||
|
|
||||||
|
//TODO to libs
|
||||||
|
type WebDEApplication interface {
|
||||||
|
// Render()
|
||||||
|
GetAppID() string
|
||||||
|
PublicRoutes(*gin.RouterGroup)
|
||||||
|
PrivateRoutes(*gin.RouterGroup)
|
||||||
|
GetPath() string
|
||||||
|
GetManifest() ApplicationManifest
|
||||||
|
// GEtHtml()
|
||||||
|
// GetId() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApplicationManifest struct {
|
||||||
|
AppId string `bson:"appid" json:"appId"`
|
||||||
|
Js []string `bson:"js" json:"js"`
|
||||||
|
Css []string `bson:"css" json:"css"`
|
||||||
|
Iconpath string `bson:"iconpath" json:"iconpath"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewApplicationsStorage(apps map[string]WebDEApplication, webfs *webfilesystem.WebFileSystem) *ApplicationsStorage {
|
||||||
|
return &ApplicationsStorage{
|
||||||
|
Apps: apps,
|
||||||
|
fs: webfs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApplicationsStorage struct {
|
||||||
|
Apps map[string]WebDEApplication
|
||||||
|
fs *webfilesystem.WebFileSystem
|
||||||
|
}
|
||||||
|
|
||||||
|
func (as *ApplicationsStorage) createApp(appName string, appId string, appPath string) error {
|
||||||
|
appBundleName := appName + ".app"
|
||||||
|
newAppBundleHeader := webfilesystem.FileHeader{
|
||||||
|
MongoId: primitive.NewObjectID(),
|
||||||
|
Name: appBundleName,
|
||||||
|
Type: "directory",
|
||||||
|
Icon: "",
|
||||||
|
Data: primitive.NewObjectID(),
|
||||||
|
}
|
||||||
|
newAppBundleData := webfilesystem.DirectoryData{
|
||||||
|
MongoId: primitive.NewObjectID(),
|
||||||
|
Parent: primitive.NewObjectID(),
|
||||||
|
Children: []primitive.ObjectID{},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err := as.fs.Write(appPath+"/"+appBundleName, &newAppBundleHeader, &newAppBundleData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
newAppData := ApplicationManifest{
|
||||||
|
AppId: appId,
|
||||||
|
Js: []string{},
|
||||||
|
Css: []string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
newAppFile := webfilesystem.FileHeader{
|
||||||
|
MongoId: primitive.NewObjectID(),
|
||||||
|
Name: ".appmanifest",
|
||||||
|
Type: "application-manifest",
|
||||||
|
Icon: "",
|
||||||
|
Data: primitive.NewObjectID(),
|
||||||
|
}
|
||||||
|
_, _, err = as.fs.Write(appPath+"/"+appBundleName+"/"+newAppFile.Name, &newAppFile, newAppData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (aStorage *ApplicationsStorage) PrivateRoute(route *gin.RouterGroup) {
|
||||||
|
route.GET("/get", func(ctx *gin.Context) {
|
||||||
|
appId := ctx.Query("appid")
|
||||||
|
if appId == "" {
|
||||||
|
ctx.Status(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// app, isExist := aStorage.Apps[appId]
|
||||||
|
// if !isExist {
|
||||||
|
// ctx.Status(http.StatusNoContent)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// ctx.JSON(http.StatusOK, app.GetManifest())
|
||||||
|
ctx.String(http.StatusMovedPermanently, "Obsolete")
|
||||||
|
})
|
||||||
|
|
||||||
|
route.GET("/loadApp", func(ctx *gin.Context) {
|
||||||
|
appPath := ctx.Query("path")
|
||||||
|
if appPath == "" {
|
||||||
|
ctx.Status(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
appManifestData := ApplicationManifest{}
|
||||||
|
fileHeader, err := aStorage.fs.Read(path.Join(appPath, ".appmanifest"), &appManifestData)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Status(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if fileHeader.Type != "application-manifest" {
|
||||||
|
ctx.Status(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusOK, appManifestData)
|
||||||
|
})
|
||||||
|
|
||||||
|
route.GET("/createApp", func(ctx *gin.Context) {
|
||||||
|
appId := ctx.Query("appId")
|
||||||
|
if appId == "" {
|
||||||
|
ctx.Status(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
appName := ctx.Query("appName")
|
||||||
|
if appName == "" {
|
||||||
|
ctx.Status(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
appPath := ctx.Query("path")
|
||||||
|
if appPath == "" {
|
||||||
|
ctx.Status(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := aStorage.createApp(appId, appName, appPath)
|
||||||
|
if err != nil {
|
||||||
|
ctx.String(http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Status(http.StatusOK)
|
||||||
|
})
|
||||||
|
}
|
5
errormessage/errormessage.go
Normal file
5
errormessage/errormessage.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package errormessage
|
||||||
|
|
||||||
|
type ErrorMessage struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
BIN
front/dist/Charcoal.cb9045e5.woff2
vendored
Normal file
BIN
front/dist/Charcoal.cb9045e5.woff2
vendored
Normal file
Binary file not shown.
BIN
front/dist/Geneva.41461b69.woff2
vendored
Normal file
BIN
front/dist/Geneva.41461b69.woff2
vendored
Normal file
Binary file not shown.
157
front/dist/apps/about-me/about-me.css
vendored
Normal file
157
front/dist/apps/about-me/about-me.css
vendored
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: Geneva;
|
||||||
|
src: url("../../Geneva.41461b69.woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Charcoal;
|
||||||
|
src: url("../../Charcoal.cb9045e5.woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
.large-system-font, .ShortBio > .Text > .Name, .Island .Title, .Island .Key {
|
||||||
|
letter-spacing: .35px;
|
||||||
|
font-family: Charcoal;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small-system-font, .views-font {
|
||||||
|
font-family: Geneva;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PersPropsContent {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PersPropsContent .PropsView {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PropertiesList {
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 0;
|
||||||
|
order: 0;
|
||||||
|
align-self: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 12px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PropertiesList .ShortBio {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ShortBio .Image {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ShortBio .Text {
|
||||||
|
align-self: stretch;
|
||||||
|
align-items: left;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
order: 0;
|
||||||
|
gap: 1px;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PropertiesList .Links {
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: end;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Links > a {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: end;
|
||||||
|
gap: 2px;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PropertiesList .Links .Link {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PropertiesList .Island {
|
||||||
|
border: 1px solid #888;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
box-shadow: 1px 1px #fff, inset 1px 1px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Island .Title {
|
||||||
|
background-color: #ddd;
|
||||||
|
max-width: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
top: -9px;
|
||||||
|
left: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Island .Content {
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 12px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Island .Row {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 5px;
|
||||||
|
margin-left: 12px;
|
||||||
|
margin-right: 12px;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Island .Key {
|
||||||
|
text-align: end;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 34%;
|
||||||
|
position: relative;
|
||||||
|
top: -1.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Island .KeyComment {
|
||||||
|
color: #646464;
|
||||||
|
text-align: end;
|
||||||
|
white-space: normal;
|
||||||
|
font-size: 9px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Island .Values {
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: left;
|
||||||
|
gap: 5px;
|
||||||
|
width: 55%;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*# sourceMappingURL=about-me.css.map */
|
1
front/dist/apps/about-me/about-me.css.map
vendored
Normal file
1
front/dist/apps/about-me/about-me.css.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"mappings":"ACiBA;;;;;AAKA;;;;;AAKA;;;;;;AAMA;;;;AD/BA;;;;;;;;;;AAYA;;;;;AAKA;;;;;;;;;;;AAkBA;;;;;;;;AAsBA;;;;;;AAMA;;;;;;;;;;;AAuBA;;;;;;;;;;AAiBA;;;;;;;;;AAeA;;;;;AAMA;;;;;;;;AAeA;;;;;;;;;AAWA;;;;;;;;;AAWA;;;;;;;;;;AAUA;;;;;;;;AAcA;;;;;;;;AAUA","sources":["src/apps/about-me/about-me.less","src/theme.less"],"sourcesContent":["@import \"../../theme.less\";\n\n.PersPropsContent{\n width: 100%;\n height: 100%;\n\n /* Auto layout */\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: flex-start;\n padding: 0px;\n}\n\n.PersPropsContent .PropsView{\n /* background-color: rebeccapurple; */\n width: 100%;\n height: auto;\n}\n.PropertiesList{\n /* width: 100%;\n height: auto; */\n\n /* Inside auto layout */\n order: 0;\n align-self: flex-start;\n flex-grow: 0;\n\n /* Auto layout */\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n padding: 12px;\n gap:16px;\n}\n\n\n.PropertiesList .ShortBio{\n /* width: 100%;\n height: auto; */\n /* margin-right: -20px; */\n\n // background-color: aquamarine;\n /* Inside auto layout */\n width: 100%;\n // flex: none;\n // order: 0;\n // align-self: stretch;\n // flex-grow: 1;\n\n /* Auto layout */\n display: flex;\n flex-direction: row;\n align-items: center;\n // padding: 0px;\n // margin-right: 20;\n gap:15px;\n}\n\n.ShortBio .Image{\n width: 48px;\n height: 48px;\n padding-left: 10px;\n}\n\n.ShortBio .Text{\n /* width: 100%;\n height: auto; */\n\n /* Inside auto layout */\n flex: none;\n order: 0;\n align-self: stretch;\n flex-grow: 1;\n \n /* Auto layout */\n display: flex;\n flex-direction: column;\n align-items: left;\n padding: 0px;\n gap:1px;\n}\n\n.ShortBio > .Text > .Name{\n &:extend(.large-system-font);\n // background-color: aqua;\n}\n\n.PropertiesList .Links {\n // position: absolute;\n // right: 14px;\n // top: 27px;\n // background-color: aqua;\n height: auto;\n width: auto;\n\n // background-color: aqua;\n /* Auto layout */\n display: flex;\n flex-direction: column;\n align-items: end;\n justify-content: center;\n padding: 0px;\n // gap:4px;\n}\n.Links > a{\n /* Auto layout */\n display: flex;\n flex-direction: row;\n align-items: end;\n justify-content: center;\n padding: 0px;\n gap: 2px;\n}\n.Links > a > .link-lable{\n // background-color: aqua;\n // line-height: 60px;\n // display:table\n}\n\n.PropertiesList .Links .Link {\n /* background-color:brown; */\n width: 16px;\n height: 16px;\n}\n\n.PropertiesList .Island{\n width: 100%;\n height: auto;\n border: 1px solid #888888;\n box-shadow: 1px 1px 0px #FFFFFF, inset 1px 1px 0px #FFFFFF;\n padding-bottom: 10px;\n\n /* Auto layout */\n /* display: flex;\n flex-direction: column;\n align-items: center;\n padding: 0px;\n gap:1px; */\n}\n\n.Island .Title {\n //FIXME\n &:extend(.large-system-font);\n position:relative;\n display: inline-block;\n max-width: 100%;\n background-color: #DDDDDD;\n left: 12px;\n top: -9px;\n}\n\n.Island .Content{\n width: 100%;\n /* top: 0px; */\n /* Auto layout */\n display: flex;\n flex-direction: column;\n justify-content: center;\n padding: 0px;\n gap: 12px;\n}\n\n.Island .Row{\n margin-left: 12px;\n margin-right: 12px;\n /* Auto layout */\n display: flex;\n flex-direction: row;\n justify-content: center;\n padding: 0px;\n gap: 5px;\n}\n.Island .Key{\n position: relative;\n &:extend(.large-system-font);\n // font-family: \"Virtue\";\n // font-size: 11px;\n // letter-spacing: 0.35px;\n text-align: end;\n width: 34%;\n white-space: nowrap;\n top: -1.5px;\n\n /* font-weight: bold; */\n}\n\n.Island .KeyComment{\n /* color: rgb(129, 129, 129); TODO*/\n color: #646464;\n font-size: 9px;\n font-style: italic;\n text-align: end;\n white-space:normal;\n /* filter: drop-shadow(-.5px -.5px 0px #616161); */\n}\n\n.Island .Values{\n width: 55%;\n display: flex;\n flex-direction: column;\n justify-content: left;\n padding: 0px;\n gap: 5px;\n\n}\n\n.Values .Value{\n /* width: 55%; */\n\n}",null],"names":[],"version":3,"file":"about-me.css.map","sourceRoot":"/__parcel_source_root/"}
|
81
front/dist/apps/finder/finder.css
vendored
Normal file
81
front/dist/apps/finder/finder.css
vendored
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: Geneva;
|
||||||
|
src: url("../../Geneva.41461b69.woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Charcoal;
|
||||||
|
src: url("../../Charcoal.cb9045e5.woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
.large-system-font {
|
||||||
|
letter-spacing: .35px;
|
||||||
|
font-family: Charcoal;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small-system-font, .views-font {
|
||||||
|
font-family: Geneva;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adjective {
|
||||||
|
border: 1px solid #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.convex {
|
||||||
|
box-shadow: 1px 1px #00000040, inset -1px -1px #00000045, inset 1px 1px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border .grey {
|
||||||
|
border: 1px solid #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border .black {
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow .grey {
|
||||||
|
box-shadow: 1px 1px #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow .black {
|
||||||
|
box-shadow: 1px 1px #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rows-fill-shadowed {
|
||||||
|
filter: drop-shadow(1px 1px #777);
|
||||||
|
background: linear-gradient(#0000 0%, #fff 0% 50%, #0000 50%) 0 0 / 2px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.finder-content {
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: start;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.finder-content > .tool-bar {
|
||||||
|
border-bottom: 1px solid #555;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-frame.Focused .tool-bar {
|
||||||
|
border-bottom: 1px solid #000;
|
||||||
|
box-shadow: inset -1px -1px #00000045, inset 1px 1px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.finder-content > .file-view-container {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*# sourceMappingURL=finder.css.map */
|
1
front/dist/apps/finder/finder.css.map
vendored
Normal file
1
front/dist/apps/finder/finder.css.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"mappings":"ACiBA;;;;;AAKA;;;;;AAKA;;;;;;AAMA;;;;ACjCA;;;;AAIA;;;;AAMA;;;;AAAA;;;;AAUA;;;;AAAA;;;;AAWA;;;;;AF5BA;;;;;;;;;;AAYA;;;;;;AAMA;;;;;AAKA","sources":["src/apps/finder/finder.less","src/theme.less","src/wde/effects.less"],"sourcesContent":["@import \"../../theme.less\";\n@import \"../../wde/effects.less\";\n\n.finder-content {\n width: 100%;\n height: 100%;\n\n /* Auto layout */\n display: flex;\n flex-direction: column;\n justify-content: start;\n align-items: flex-start;\n padding: 0px;\n}\n\n.finder-content > .tool-bar{\n width: 100%;\n min-height: 20px;\n border-bottom: @eff-border-grey;\n}\n\n.window-frame.Focused .tool-bar{\n border-bottom: 1px solid #000000;\n box-shadow: @eff-box-shadow-convex;\n}\n\n.finder-content > .file-view-container{\n width: 100%;\n height: 100%;\n\n // background-color: #FFFFFF;\n\n /* Auto layout */\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: flex-start;\n padding: 0px;\n}",null,null],"names":[],"version":3,"file":"finder.css.map","sourceRoot":"/__parcel_source_root/"}
|
370
front/dist/desktop.css
vendored
Normal file
370
front/dist/desktop.css
vendored
Normal file
@ -0,0 +1,370 @@
|
|||||||
|
.WdePrimitives .adjective {
|
||||||
|
border: 1px solid #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WdePrimitives .black-border {
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView.DragDropBorder {
|
||||||
|
box-shadow: inset 0 0 0 4px #99c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView .FlexContainer {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
flex-flow: wrap;
|
||||||
|
place-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 20px 50px;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
margin: 15px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView .Tile {
|
||||||
|
flex-flow: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2px;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView .Icon {
|
||||||
|
background-size: cover;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView .Selected .Icon {
|
||||||
|
filter: brightness(.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView .Lable {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView .Selected .Lable {
|
||||||
|
white-space: nowrap;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar-place {
|
||||||
|
border-left: 1px solid #555;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
order: 0;
|
||||||
|
align-self: stretch;
|
||||||
|
width: 14px;
|
||||||
|
height: 100%;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Focused .active .scrollbar-place {
|
||||||
|
background-color: #aaa;
|
||||||
|
border-left: 1px solid #000;
|
||||||
|
box-shadow: inset -1px 0 #ffffff4a, inset -2px 0 #ffffff30, inset 1px 1px #00000024, inset 2px 2px #00000030;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-element {
|
||||||
|
visibility: hidden;
|
||||||
|
background: #99f;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
width: 14px;
|
||||||
|
height: 31px;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
box-shadow: 0 -1px #000, 0 1px #000, 0 2px #00000021, 0 3px #00000030, inset 0 1px #ffffff80, inset 1px 0 #ffffff80, inset -1px -1px #6666cce8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Focused .active .scroll-element {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drag-element {
|
||||||
|
pointer-events: none;
|
||||||
|
filter: drop-shadow(1px 1px #339);
|
||||||
|
background: linear-gradient(#0000 0%, #ccf 0% 50%, #0000 50%) 0 0 / 2px 2px;
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
margin-left: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ScrollContent {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ScrollContent::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adjective {
|
||||||
|
border: 1px solid #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.convex {
|
||||||
|
box-shadow: 1px 1px #00000040, inset -1px -1px #00000045, inset 1px 1px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border .grey {
|
||||||
|
border: 1px solid #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border .black {
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow .grey {
|
||||||
|
box-shadow: 1px 1px #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow .black {
|
||||||
|
box-shadow: 1px 1px #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rows-fill-shadowed, .window-frame.Focused .title-bar .visual-drag-area {
|
||||||
|
filter: drop-shadow(1px 1px #777);
|
||||||
|
background: linear-gradient(#0000 0%, #fff 0% 50%, #0000 50%) 0 0 / 2px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wde-button {
|
||||||
|
background-color: #ddd;
|
||||||
|
border: 1px solid #000;
|
||||||
|
border-radius: 3px;
|
||||||
|
width: auto;
|
||||||
|
height: 20px;
|
||||||
|
box-shadow: inset -1px -1px #00000045, inset 1px 1px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wde-button:active {
|
||||||
|
background-color: #666;
|
||||||
|
box-shadow: inset 1px 1px #00000045, inset -1px -1px gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ContentBorder {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ContextMenu {
|
||||||
|
background-color: #ddd;
|
||||||
|
border: 1px solid #000;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ContextMenu .Content {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ContextMenu .Row {
|
||||||
|
width: 100%;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ContextMenu .Row:hover {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #339;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ContextMenu .Row .Lable {
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-left: 20px;
|
||||||
|
margin-right: 12px;
|
||||||
|
font-family: Virtue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Geneva;
|
||||||
|
src: url("Geneva.41461b69.woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Charcoal;
|
||||||
|
src: url("Charcoal.cb9045e5.woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
.large-system-font, .title-bar .lable {
|
||||||
|
letter-spacing: .35px;
|
||||||
|
font-family: Charcoal;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small-system-font, .views-font, body {
|
||||||
|
font-family: Geneva;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-frame {
|
||||||
|
background-color: #ddd;
|
||||||
|
border: 1px solid #555;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
order: 1;
|
||||||
|
align-self: stretch;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 2px 6px 4px 4px;
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
box-shadow: 1px 1px #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-frame.Focused {
|
||||||
|
background-color: #ccc;
|
||||||
|
border: 1px solid #000;
|
||||||
|
box-shadow: 1px 1px #555, inset -1px -1px #00000045, inset 1px 1px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-border {
|
||||||
|
background-color: #eee;
|
||||||
|
border: 1px solid #555;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Focused .content-border {
|
||||||
|
background-color: #ddd;
|
||||||
|
border: 1px solid #000;
|
||||||
|
box-shadow: -1px -1px #00000040, 1px 1px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-bar {
|
||||||
|
flex-direction: row;
|
||||||
|
flex: none;
|
||||||
|
order: 0;
|
||||||
|
justify-content: center;
|
||||||
|
align-self: stretch;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
width: 100%;
|
||||||
|
height: 13px;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-bar .lable {
|
||||||
|
color: gray;
|
||||||
|
pointer-events: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-frame.Focused .title-bar .lable {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-frame.Focused .title-bar .visual-drag-area {
|
||||||
|
pointer-events: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-bar > .icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-bar > .button {
|
||||||
|
visibility: hidden;
|
||||||
|
background: linear-gradient(135deg, #999 18.18%, #fff 81.82%);
|
||||||
|
border: 1px solid #222;
|
||||||
|
flex: none;
|
||||||
|
order: 0;
|
||||||
|
width: 11px;
|
||||||
|
height: 11px;
|
||||||
|
padding: 0%;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
box-shadow: .5px .5px 0 .5px #fff, -.5px -.5px 0 .5px #00000040, inset 1px 1px #ffffff80, inset -1px -1px #00000045;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-bar > .button:active {
|
||||||
|
background-color: #0006;
|
||||||
|
box-shadow: .5px .5px 0 .5px #fff, -.5px -.5px 0 .5px #00000040;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-frame.Focused .title-bar > .button {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.NoClick {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Click {
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
src: url("Geneva.41461b69.woff2");
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
touch-action: manipulation;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 11px;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
#applications {
|
||||||
|
visibility: hidden;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
|
||||||
|
#windows-layer {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
|
||||||
|
#desktop-layer {
|
||||||
|
background-color: #99c;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*# sourceMappingURL=desktop.css.map */
|
1
front/dist/desktop.css.map
vendored
Normal file
1
front/dist/desktop.css.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"mappings":"ACAA;;;;AAAA;;;;ACCA;;;;;AAWA;;;;AAKA;;;;;;;;;;;;;AAqBA;;;;;AAKA;;;;;;;;;;;AAkBA;;;;;;AAeA;;;;AAIA;;;;AAIA;;;;;;ACrEA;;;;;;;;;;;;AAsBA;;;;;;AASA;;;;;;;;;;;;;;;AAyBA;;;;AAIA;;;;;;;;;AAeA;;;;;;;AAgBA;;;;;AC1GA;;;;AAIA;;;;AAMA;;;;AAAA;;;;AAUA;;;;AAAA;;;;AAWA;;;;;AE5BA;;;;;;;;;AACI;;;;;ACJJ;;;;;;AAUA;;;;;;;;AAUA;;;;;;;;;AAgBA;;;;;AAYA;;;;;AAKA;;;;;;;ACpCA;;;;;AAKA;;;;;AAKA;;;;;;AAMA;;;;AC9BA;;;;;;;;;;;;;;;AAyBA;;;;;;AAOA;;;;;;;;AAUA;;;;;;AJ1CA;;;;;;;;;;;;;;AAmBA;;;;;;;;AAcA;;;;AAIA;;;;;;AAOA;;;;;AAOA;;;;;;;;;;;;;;AAQI;;;;;AAmBJ;;;;ALvEA;;;;AAGA;;;;AAYA;;;;;AAKA;;;;;;;;;;;;;;AAwBA;;;;;;;AAOA;;;;;;AAOA","sources":["src/desktop.less","src/wde/primitives.less","src/wde/widgets/file-view/file-view.less","src/wde/widgets/scrollbar/scrollbar.less","src/wde/effects.less","src/wde/widgets/title-bar/title-bar.less","src/wde/widgets/button/button.less","src/wde/widgets/basic-widgets.less","src/theme.less","src/wde/window-frame.less"],"sourcesContent":["@import \"./wde/primitives.less\";\n@import \"./wde/widgets/file-view/file-view.less\";\n@import \"./wde/widgets/scrollbar/scrollbar.less\";\n@import \"./wde/widgets/button/button.less\";\n// @import \"./wde/legacy-ui.less\";\n@import \"./wde/widgets/basic-widgets.less\";\n@import \"./theme.less\";\n@import \"./wde/window-frame.less\";\n@import \"./wde/widgets/title-bar/title-bar.less\";\n\n.NoClick {\n pointer-events: none;\n}\n.Click {\n pointer-events: all;\n}\n// .DragArea\n\n// *{\n// font-family: Verdana, Geneva, sans-serif;\n// font-size: 11px;\n// font-style: normal;\n// font-weight:initial;\n// }\n\n*::-webkit-scrollbar { /* WebKit */\n width: 0;\n height: 0;\n}\n\nbody{\n &:extend(.views-font);\n // zoom: var(--zoom);\n position: absolute;\n width: 100%;\n height: 100%;\n margin: 0px;\n\n font-size: 11px;\n\n // font-family: \"Geneva\";\n src:url(\"./fonts/Geneva.woff2\");\n\n /* font: normal 14px Summer Pixel 22, \"res/SummerPixel22Regular.ttf\"; */\n -webkit-touch-callout: none; /* iOS Safari */\n -webkit-user-select: none; /* Safari */\n -khtml-user-select: none; /* Konqueror HTML */\n -moz-user-select: none; /* Old versions of Firefox */\n -ms-user-select: none; /* Internet Explorer/Edge */\n user-select: none; /* Non-prefixed version, currently\n supported by Chrome, Edge, Opera and Firefox */\n touch-action: manipulation;\n}\n\n#applications{\n position: static;\n width: 0px;\n height: 0px;\n visibility: hidden;\n}\n\n#windows-layer {\n width: 0px;\n height: 0px;\n /* position: fixed; */\n position: static;\n}\n\n#desktop-layer{\n position: fixed;\n /* margin: 0px; */\n width: 100%;\n height: 100%;\n background-color: @col-ceil;\n}",null,null,null,null,null,null,null,null,null],"names":[],"version":3,"file":"desktop.css.map","sourceRoot":"/__parcel_source_root/"}
|
168
front/dist/mobile.css
vendored
Normal file
168
front/dist/mobile.css
vendored
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
.WdePrimitives .adjective {
|
||||||
|
border: 1px solid #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WdePrimitives .black-border {
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mobile-sunboard {
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#icons {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.apps-list {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex: 1 0 0;
|
||||||
|
align-content: flex-start;
|
||||||
|
align-self: stretch;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 64px 0;
|
||||||
|
padding: 64px 16px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-icon {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
width: 100px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-icon .icon {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Geneva;
|
||||||
|
src: url("Geneva.41461b69.woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Charcoal;
|
||||||
|
src: url("Charcoal.cb9045e5.woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
.large-system-font {
|
||||||
|
letter-spacing: .35px;
|
||||||
|
font-family: Charcoal;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small-system-font, .views-font, body {
|
||||||
|
font-family: Geneva;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adjective {
|
||||||
|
border: 1px solid #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.convex {
|
||||||
|
box-shadow: 1px 1px #00000040, inset -1px -1px #00000045, inset 1px 1px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border .grey {
|
||||||
|
border: 1px solid #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border .black {
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow .grey {
|
||||||
|
box-shadow: 1px 1px #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow .black {
|
||||||
|
box-shadow: 1px 1px #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rows-fill-shadowed {
|
||||||
|
filter: drop-shadow(1px 1px #777);
|
||||||
|
background: linear-gradient(#0000 0%, #fff 0% 50%, #0000 50%) 0 0 / 2px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wde-button, .wde-mobile-button {
|
||||||
|
background-color: #ddd;
|
||||||
|
border: 1px solid #000;
|
||||||
|
border-radius: 3px;
|
||||||
|
width: auto;
|
||||||
|
height: 20px;
|
||||||
|
box-shadow: inset -1px -1px #00000045, inset 1px 1px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wde-button:active, .wde-mobile-button:active {
|
||||||
|
background-color: #666;
|
||||||
|
box-shadow: inset 1px 1px #00000045, inset -1px -1px gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Geneva;
|
||||||
|
src: url("Geneva.41461b69.woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
touch-action: manipulation;
|
||||||
|
background-color: silver;
|
||||||
|
background-position: 0 0, 0 0, -5px -5px, 5px 5px;
|
||||||
|
background-size: 10px 10px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mobile-app-views {
|
||||||
|
background: #ddd;
|
||||||
|
border: 1px solid #000;
|
||||||
|
border-radius: 5px;
|
||||||
|
position: absolute;
|
||||||
|
inset: 16px 16px 100px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 1px 1px #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls-bar {
|
||||||
|
justify-content: center;
|
||||||
|
align-self: stretch;
|
||||||
|
align-items: center;
|
||||||
|
gap: 53px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-app-view {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wde-mobile-button {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 95px;
|
||||||
|
height: 35px;
|
||||||
|
padding-right: 5px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*# sourceMappingURL=mobile.css.map */
|
1
front/dist/mobile.css.map
vendored
Normal file
1
front/dist/mobile.css.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"mappings":"ACAA;;;;AAAA;;;;ACGA;;;;;;;;;AAWA;;;;;AAaA;;;;;;;;;;;AAYA;;;;;;;;AAaA;;;;;ACnCA;;;;;AAKA;;;;;AAKA;;;;;;AAMA;;;;ACjCA;;;;AAIA;;;;AAMA;;;;AAAA;;;;AAUA;;;;AAAA;;;;AAWA;;;;;AC5BA;;;;;;;;;AACI;;;;;ALCJ;;;;;AAKA;;;;;;;;;;;;;;;;AAwCA;;;;;;;;;;AAaA;;;;;;;;;;;;AAiBA;;;;;AAOA","sources":["src/mobile.less","src/wde/primitives.less","src/wde/sunboard/sunboard-mobile.less","src/theme.less","src/wde/effects.less","src/wde/widgets/button/button.less"],"sourcesContent":["@import \"./wde/sunboard/sunboard-mobile.less\";\n@import \"./theme.less\";\n@import \"./wde/effects.less\";\n@import \"./wde/widgets/button/button.less\";\n\n@font-face{\n font-family: \"Geneva\";\n src:url(\"./fonts/Geneva.woff2\");\n} \n\nbody{\n &:extend(.views-font);\n // zoom: 2;\n position: absolute;\n width: 100%;\n height: 100%;\n margin: 0px;\n\n\n font-size: 12px;\n\n /* font: normal 14px Summer Pixel 22, \"res/SummerPixel22Regular.ttf\"; */\n -webkit-touch-callout: none; /* iOS Safari */\n -webkit-user-select: none; /* Safari */\n -khtml-user-select: none; /* Konqueror HTML */\n -moz-user-select: none; /* Old versions of Firefox */\n -ms-user-select: none; /* Internet Explorer/Edge */\n user-select: none; /* Non-prefixed version, currently\n supported by Chrome, Edge, Opera and Firefox */\n touch-action: manipulation;\n\n background-color: @col-argent;\n // /* Auto layout */\n // display: flex;\n // flex-direction: column;\n // align-items: flex-start;\n // justify-content: flex-start;\n // margin: 32px;\n\n // background-image:\n // linear-gradient(45deg, @col-argent 25%, transparent 25%),\n // linear-gradient(45deg, transparent 75%, @col-argent 75%),\n // linear-gradient(45deg, transparent 75%, @col-argent 75%),\n // linear-gradient(45deg, @col-argent 25%, #777777 25%); \n\n background-size:10px 10px; \n\n background-position:0 0, 0 0, -5px -5px, 5px 5px;\n}\n\n#mobile-app-views{\n position: absolute;\n // background-color: aqua;\n inset: 16px;\n bottom: 100px;\n \n border-radius: 5px;\n border: @eff-border-black;\n box-shadow: @eff-box-shadow-black;\n background: @col-gainsboro;\n overflow: hidden;\n}\n\n#controls-bar{\n position: absolute;\n\n width: 100%;\n height: 100px;\n // background-color: @col-argent;\n bottom: 0px;\n\n /* Auto layout */\n display: flex;\n // padding: 10px;\n justify-content: center;\n align-items: center;\n gap: 53px;\n align-self: stretch;\n}\n\n.mobile-app-view{\n // background-color: burlywood;\n width: 100%;\n height: 100%;\n // position: absolute;\n}\n\n.wde-mobile-button{\n &:extend(.wde-button);\n &:active{\n &:extend(.wde-button:active);\n }\n height: 35px;\n width: 95px;\n /* Auto layout */\n display: flex;\n // padding: 10px;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n padding-right: 5px;\n // gap: 53px;\n // align-self: stretch;\n}\n\n.wde-mobile-button > .icon{\n \n // width: 8rem;\n // height: 8rem;\n}",null,null,null,null,null],"names":[],"version":3,"file":"mobile.css.map","sourceRoot":"/__parcel_source_root/"}
|
5873
front/package-lock.json
generated
Normal file
5873
front/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
6
front/package.json
Normal file
6
front/package.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"devDependencies": {
|
||||||
|
"@parcel/transformer-less": "^2.9.3",
|
||||||
|
"parcel": "^2.9.3"
|
||||||
|
}
|
||||||
|
}
|
61
front/src/apps/about-me/about-me.js
Normal file
61
front/src/apps/about-me/about-me.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import WDEApplication from "../../wde/application.js"
|
||||||
|
import AbstractWebDesktopEnvironment from "../../wde/wde.js"
|
||||||
|
export default class AboutMe extends WDEApplication{
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {AbstractWebDesktopEnvironment} wde
|
||||||
|
*/
|
||||||
|
constructor(wde, appManifest){
|
||||||
|
super(wde, "AboutMe", appManifest)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {[]string} args
|
||||||
|
* @param {Object} runContext
|
||||||
|
*/
|
||||||
|
async NewWindow(args, runContext){
|
||||||
|
let html = await this.#renderView(runContext)
|
||||||
|
|
||||||
|
let newWindow = this.WDE().Decorat.CreateNewWindow(this.AppId, 360, document.body.clientHeight*0.8)
|
||||||
|
// console.log(html)
|
||||||
|
// return
|
||||||
|
newWindow.innerHTML = html
|
||||||
|
newWindow.style.height = 'auto'
|
||||||
|
|
||||||
|
|
||||||
|
newWindow.querySelector("#closeWindowButton").addEventListener('click', () => {
|
||||||
|
super.WDE().CloseWindow(newWindow)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string[]} args
|
||||||
|
* @param {import("../../wde/wde.js").runContext} runContext
|
||||||
|
*/
|
||||||
|
async NewView(args, runContext){
|
||||||
|
let html = await this.#renderView(runContext)
|
||||||
|
let newView = super.WDE().Decorat.CreateNewView(this.AppId)
|
||||||
|
newView.innerHTML = html
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("../../wde/wde.js").runContext} runContext
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async #renderView(runContext){
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
path: `:/aboutme.props`,
|
||||||
|
})
|
||||||
|
const response = await fetch(`/app/${this.AppId}/render?`+ params,{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(runContext)
|
||||||
|
})
|
||||||
|
if (response.status != 200){
|
||||||
|
// super.WDE().Alert("Error TODO") //TODO
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text() //Validate
|
||||||
|
return html
|
||||||
|
}
|
||||||
|
}
|
211
front/src/apps/about-me/about-me.less
Normal file
211
front/src/apps/about-me/about-me.less
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
@import "../../theme.less";
|
||||||
|
|
||||||
|
.PersPropsContent{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PersPropsContent .PropsView{
|
||||||
|
/* background-color: rebeccapurple; */
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.PropertiesList{
|
||||||
|
/* width: 100%;
|
||||||
|
height: auto; */
|
||||||
|
|
||||||
|
/* Inside auto layout */
|
||||||
|
order: 0;
|
||||||
|
align-self: flex-start;
|
||||||
|
flex-grow: 0;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 12px;
|
||||||
|
gap:16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.PropertiesList .ShortBio{
|
||||||
|
/* width: 100%;
|
||||||
|
height: auto; */
|
||||||
|
/* margin-right: -20px; */
|
||||||
|
|
||||||
|
// background-color: aquamarine;
|
||||||
|
/* Inside auto layout */
|
||||||
|
width: 100%;
|
||||||
|
// flex: none;
|
||||||
|
// order: 0;
|
||||||
|
// align-self: stretch;
|
||||||
|
// flex-grow: 1;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
// padding: 0px;
|
||||||
|
// margin-right: 20;
|
||||||
|
gap:15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ShortBio .Image{
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ShortBio .Text{
|
||||||
|
/* width: 100%;
|
||||||
|
height: auto; */
|
||||||
|
|
||||||
|
/* Inside auto layout */
|
||||||
|
flex: none;
|
||||||
|
order: 0;
|
||||||
|
align-self: stretch;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: left;
|
||||||
|
padding: 0px;
|
||||||
|
gap:1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ShortBio > .Text > .Name{
|
||||||
|
&:extend(.large-system-font);
|
||||||
|
// background-color: aqua;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PropertiesList .Links {
|
||||||
|
// position: absolute;
|
||||||
|
// right: 14px;
|
||||||
|
// top: 27px;
|
||||||
|
// background-color: aqua;
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
|
||||||
|
// background-color: aqua;
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: end;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0px;
|
||||||
|
// gap:4px;
|
||||||
|
}
|
||||||
|
.Links > a{
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: end;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0px;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
.Links > a > .link-lable{
|
||||||
|
// background-color: aqua;
|
||||||
|
// line-height: 60px;
|
||||||
|
// display:table
|
||||||
|
}
|
||||||
|
|
||||||
|
.PropertiesList .Links .Link {
|
||||||
|
/* background-color:brown; */
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PropertiesList .Island{
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
border: 1px solid #888888;
|
||||||
|
box-shadow: 1px 1px 0px #FFFFFF, inset 1px 1px 0px #FFFFFF;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
/* display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0px;
|
||||||
|
gap:1px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.Island .Title {
|
||||||
|
//FIXME
|
||||||
|
&:extend(.large-system-font);
|
||||||
|
position:relative;
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 100%;
|
||||||
|
background-color: #DDDDDD;
|
||||||
|
left: 12px;
|
||||||
|
top: -9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Island .Content{
|
||||||
|
width: 100%;
|
||||||
|
/* top: 0px; */
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0px;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Island .Row{
|
||||||
|
margin-left: 12px;
|
||||||
|
margin-right: 12px;
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0px;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
.Island .Key{
|
||||||
|
position: relative;
|
||||||
|
&:extend(.large-system-font);
|
||||||
|
// font-family: "Virtue";
|
||||||
|
// font-size: 11px;
|
||||||
|
// letter-spacing: 0.35px;
|
||||||
|
text-align: end;
|
||||||
|
width: 34%;
|
||||||
|
white-space: nowrap;
|
||||||
|
top: -1.5px;
|
||||||
|
|
||||||
|
/* font-weight: bold; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.Island .KeyComment{
|
||||||
|
/* color: rgb(129, 129, 129); TODO*/
|
||||||
|
color: #646464;
|
||||||
|
font-size: 9px;
|
||||||
|
font-style: italic;
|
||||||
|
text-align: end;
|
||||||
|
white-space:normal;
|
||||||
|
/* filter: drop-shadow(-.5px -.5px 0px #616161); */
|
||||||
|
}
|
||||||
|
|
||||||
|
.Island .Values{
|
||||||
|
width: 55%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: left;
|
||||||
|
padding: 0px;
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.Values .Value{
|
||||||
|
/* width: 55%; */
|
||||||
|
|
||||||
|
}
|
380
front/src/apps/finder/finder-window.js
Normal file
380
front/src/apps/finder/finder-window.js
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
import AbstractWebDesktopEnvironment from "../../wde/wde.js"
|
||||||
|
import Finder from "./finder.js"
|
||||||
|
|
||||||
|
|
||||||
|
export default class FinderWindow{
|
||||||
|
#appId = "Finder" //FIXME
|
||||||
|
curPath = ""
|
||||||
|
fileView = undefined
|
||||||
|
windowElem = undefined
|
||||||
|
/** @type {Finder} */
|
||||||
|
#finder
|
||||||
|
/**
|
||||||
|
* @deprecated move to this.#finder.WDE()
|
||||||
|
* @type {AbstractWebDesktopEnvironment}
|
||||||
|
*/
|
||||||
|
#wde
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {Finder}
|
||||||
|
* @param {AbstractWebDesktopEnvironment} wde
|
||||||
|
*/
|
||||||
|
constructor(finder, wde){
|
||||||
|
this.#finder = finder
|
||||||
|
this.#wde = wde
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param {Finder} finder
|
||||||
|
* @param {*} args
|
||||||
|
* @param {import("../../wde/wde.js").runContext} runContext
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async Init(finder, args, runContext){
|
||||||
|
// console.log(args)
|
||||||
|
this.#finder = finder
|
||||||
|
if (runContext.isMobile){
|
||||||
|
console.log("Mobile Finder!")
|
||||||
|
this.CreateMobileView(args, runContext)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (args[1] == "--desktop"){
|
||||||
|
let desktopNode = document.body.querySelector(`#${args[2]}`)
|
||||||
|
if (desktopNode == null){
|
||||||
|
this.#wde.Alert("Desktop node not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
path: args[0]
|
||||||
|
})
|
||||||
|
const response = await fetch(`/app/${this.#appId}/renderDesktop?` + params,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(runContext)
|
||||||
|
})
|
||||||
|
if (response.status != 200){
|
||||||
|
console.log(response.status)
|
||||||
|
// this.#wde.Alert("Error in render desktop") //TODO
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
desktopNode.innerHTML = html
|
||||||
|
|
||||||
|
// console.log(this.#wde)
|
||||||
|
|
||||||
|
this.fileView = new this.#wde.FileView(
|
||||||
|
desktopNode.querySelector(".FileTileView"), (event) =>{this.Click(event)},
|
||||||
|
(event) => { this.RightClick(event) },
|
||||||
|
(event, draggedElem) => { this.DropEvent(event, draggedElem)},
|
||||||
|
() => { this.ReRenderDir() },
|
||||||
|
this.#wde)
|
||||||
|
this.RenderDir(args[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const params = new URLSearchParams({isMobile: false}) //FIXME
|
||||||
|
const response = await fetch(`/app/${this.#appId}/render?` + params,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(runContext)
|
||||||
|
})
|
||||||
|
if (response.status != 200){
|
||||||
|
const error = await response.json()
|
||||||
|
this.#wde.Alert(error.message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
|
||||||
|
let newWindow = this.#wde.Decorat.CreateNewWindow(this.#appId, 500, 350 )
|
||||||
|
newWindow.innerHTML = html
|
||||||
|
//TODO change icons for every folder
|
||||||
|
// newWindow.querySelector(".title-bar").querySelector(".icon").setAttribute("src","/system/libs/img/icon/get?path=/Icons/GenericFolder.icn&size=16")
|
||||||
|
|
||||||
|
// console.log(newWindow.querySelector(".FileTileView"))
|
||||||
|
|
||||||
|
this.fileView = new this.#wde.FileView(
|
||||||
|
newWindow.querySelector(".FileTileView"),
|
||||||
|
(event) => { this.Click(event) },
|
||||||
|
(event) => { this.RightClick(event) },
|
||||||
|
(event, draggedElem) => { this.DropEvent(event, draggedElem)},
|
||||||
|
() => { this.ReRenderDir() },
|
||||||
|
this.#wde)
|
||||||
|
|
||||||
|
newWindow.querySelector("#closeWindowButton").addEventListener('click', () => {
|
||||||
|
this.#wde.Decorat.CloseWindow(newWindow)
|
||||||
|
})
|
||||||
|
|
||||||
|
// newWindow.querySelector("#RootButton").addEventListener('click', () =>{
|
||||||
|
// this.RenderDir('/')
|
||||||
|
// })
|
||||||
|
|
||||||
|
// newWindow.querySelector("#HomeButton").addEventListener('click', () =>{
|
||||||
|
// this.RenderDir('/home/user')
|
||||||
|
// })
|
||||||
|
|
||||||
|
// let scrollBar = new this.#wde.ScrollBar(newWindow.querySelector(".scrollbar-place"), newWindow.querySelector(".FileTileView"))
|
||||||
|
|
||||||
|
this.windowElem = newWindow
|
||||||
|
this.RenderDir(args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateDesktopWindow(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} args
|
||||||
|
* @param {import("../../wde/wde-desktop.js").runContext} runContext
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async CreateMobileView(args, runContext){
|
||||||
|
const params = new URLSearchParams({isMobile: false}) //FIXME
|
||||||
|
const response = await fetch(`/app/${this.#appId}/render?` + params,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(runContext)
|
||||||
|
})
|
||||||
|
if (response.status != 200){
|
||||||
|
const error = await response.json()
|
||||||
|
this.#finder.WDE().Alert(error.message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
// console.log(html)
|
||||||
|
// console.log(this.#finder.WDE())
|
||||||
|
let newView = this.#finder.WDE().Decorat.CreateNewView(this.#appId)
|
||||||
|
newView.innerHTML = html
|
||||||
|
|
||||||
|
this.fileView = new this.#wde.FileView(
|
||||||
|
newView.querySelector(".FileTileView"),
|
||||||
|
(event) => { this.Click(event) },
|
||||||
|
(event) => { this.RightClick(event) },
|
||||||
|
(event, draggedElem) => { this.DropEvent(event, draggedElem)},
|
||||||
|
() => { this.ReRenderDir() },
|
||||||
|
this.#wde)
|
||||||
|
|
||||||
|
// newView.querySelector("#closeWindowButton").addEventListener('click', () => {
|
||||||
|
// this.#wde.Decorat.CloseWindow(newView)
|
||||||
|
// })
|
||||||
|
|
||||||
|
// newView.querySelector("#RootButton").addEventListener('click', () =>{
|
||||||
|
// this.RenderDir('/')
|
||||||
|
// })
|
||||||
|
|
||||||
|
// newView.querySelector("#HomeButton").addEventListener('click', () =>{
|
||||||
|
// this.RenderDir('/home/user')
|
||||||
|
// })
|
||||||
|
|
||||||
|
// let scrollBar = new this.#wde.ScrollBar(newView.querySelector(".scrollbar-place"), newView.querySelector(".FileTileView"))
|
||||||
|
|
||||||
|
this.windowElem = newView
|
||||||
|
this.RenderDir(args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
*/
|
||||||
|
RenderDir(path){
|
||||||
|
this.curPath = path
|
||||||
|
this.fileView.OpenFolder(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
ReRenderDir(){
|
||||||
|
this.RenderDir(this.curPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DragEvent} event
|
||||||
|
* @param {HTMLElement} draggedElem
|
||||||
|
*/
|
||||||
|
async DropEvent(event){
|
||||||
|
// console.log(event.dataTransfer.getData("dropType"))
|
||||||
|
if (event.dataTransfer.getData("dropType") == "move"){
|
||||||
|
const sourcePath= event.dataTransfer.getData("filePath")
|
||||||
|
const targetPath = this.curPath + "/" + event.dataTransfer.getData("fileName")
|
||||||
|
const res = await this.#finder.WDE().WebFS().MoveFile(sourcePath, targetPath)
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
} else {
|
||||||
|
this.#wde.Alert("UWAGA TODO MOVE FILE ERROR") //TODO
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(event, this.curPath)
|
||||||
|
let files = event.dataTransfer.files
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
const file = files[i];
|
||||||
|
console.log("file:" + file.name)
|
||||||
|
|
||||||
|
const res = await this.#finder.WDE().WebFS().UploadFile(file, this.curPath)
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
parentPath: this.curPath,
|
||||||
|
})
|
||||||
|
const response = await fetch('/fs/upload/?' + params,
|
||||||
|
{
|
||||||
|
method: "POST", //TODO Change to PUT?
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
if (response.status != 200){
|
||||||
|
this.#wde.Alert("ERROR IN UPLOADING FILE")//TODO
|
||||||
|
} else {
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MouseEvent} event
|
||||||
|
*/
|
||||||
|
Click(event){
|
||||||
|
this.OpenFile(this.curPath, event.target.getAttribute("name"), event.target.getAttribute("filetype"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} fileName
|
||||||
|
*/
|
||||||
|
getFileExtension(fileName){
|
||||||
|
return fileName.split(".")[fileName.split(".").length - 1] //FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} filePath
|
||||||
|
*/
|
||||||
|
async OpenFile(parentPath, fileName, fileType){
|
||||||
|
// console.log(parentPath, fileName, fileType)
|
||||||
|
// const splittedPath = filePath.split("/")
|
||||||
|
// const fileName = splittedPath[splittedPath.length - 1]
|
||||||
|
|
||||||
|
const fileExtension = this.getFileExtension(fileName)
|
||||||
|
console.log(fileExtension)
|
||||||
|
switch (true) {
|
||||||
|
case fileType == "objectlink":
|
||||||
|
this.#finder.WDE().Alert("Links not supported yet")
|
||||||
|
break
|
||||||
|
case fileType == "pathlink":
|
||||||
|
let res = await WebFS.ReadPathLink(`${parentPath}/${fileName}`)
|
||||||
|
console.log(res)
|
||||||
|
this.OpenFile(res.parentPath, res.name, res.filetype)
|
||||||
|
break
|
||||||
|
case fileExtension == "app":
|
||||||
|
this.#finder.WDE().Open(`${parentPath}/${fileName}`, [])
|
||||||
|
break
|
||||||
|
case fileExtension == "blog":
|
||||||
|
this.#finder.WDE().Open(`/Applications/BlogViewer.app`, [`${parentPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
case fileType == "directory":
|
||||||
|
this.#finder.WDE().Open(`/Applications/Finder.app`, [`${parentPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
case fileExtension == "blog":
|
||||||
|
this.#finder.WDE().Open("/Applications/BlogViewer.app", [`${parentPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
case fileExtension == "jpeg" | fileExtension == "png":
|
||||||
|
this.#finder.WDE().Open("img-viewer", [`${parentPath}/${fileName}`])
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.#finder.WDE().Alert("Unsupported file type")
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MouseEvent} event
|
||||||
|
*/
|
||||||
|
RightClick(event){
|
||||||
|
this.CreateContextMenu(event.target, [event.clientY, event.clientX])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
* @param {string[]} pos
|
||||||
|
*/
|
||||||
|
async CreateContextMenu(target, pos){
|
||||||
|
let context = ""
|
||||||
|
const fileName = target.getAttribute("name") //TODO check for null
|
||||||
|
const fileType = target.getAttribute("fileType")
|
||||||
|
if (target.classList.contains("FileTileView"))
|
||||||
|
{
|
||||||
|
context = "FileTileView"
|
||||||
|
} else {
|
||||||
|
context = fileType
|
||||||
|
}
|
||||||
|
let path = ""
|
||||||
|
if (fileName === null){
|
||||||
|
path = this.curPath
|
||||||
|
} else {
|
||||||
|
path = `${this.curPath}/${fileName}`
|
||||||
|
}
|
||||||
|
const params = new URLSearchParams({context: context, path: path})
|
||||||
|
const response = await fetch(`/app/${this.#appId}/contextMenu?` + params)
|
||||||
|
if (response.status != 200){
|
||||||
|
this.#wde.Alert("ERROR in Context menu TODO"); //TODO
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
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.top = pos[0] + "px";
|
||||||
|
menu.style.left = pos[1] + "px";
|
||||||
|
|
||||||
|
menu.innerHTML = html
|
||||||
|
// menu.children[0].firstElementChild.remove()
|
||||||
|
menu.children[0].lastElementChild.remove() //FIXME Can't ommit rendering of horLine in end of menu on backend
|
||||||
|
|
||||||
|
overlay.appendChild(menu)
|
||||||
|
document.body.appendChild(overlay)
|
||||||
|
|
||||||
|
overlay.addEventListener('click', async (event) => {
|
||||||
|
if (event.target.classList.contains("Row")){ //TODO add uuid id to rows to more accurate checks??
|
||||||
|
let res = false
|
||||||
|
switch (event.target.children[0].getAttribute("action")) {
|
||||||
|
case "createPathLink":
|
||||||
|
res = await this.#finder.WDE().WebFS().CreatePathLink(`${this.curPath}/${fileName}`, `${this.curPath}/Link to ${fileName}` )
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "createDir":
|
||||||
|
res = await this.#finder.WDE().WebFS().CreateDirectory(`${this.curPath}`)
|
||||||
|
// console.log(res)
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "deleteFile":
|
||||||
|
res = await this.#finder.WDE().WebFS().DeleteFile(`${this.curPath}/${fileName}`)
|
||||||
|
// console.log(res)
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "getInfo":
|
||||||
|
this.#finder.RenderProperites(path)
|
||||||
|
break
|
||||||
|
case "openAsDir":
|
||||||
|
this.#finder.WDE().Open(`/Applications/${this.#appId}.app`,[`${this.curPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
overlay.remove()
|
||||||
|
})
|
||||||
|
overlay.addEventListener('contextmenu', (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
overlay.remove()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
63
front/src/apps/finder/finder.js
Normal file
63
front/src/apps/finder/finder.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// require("./finder.less")
|
||||||
|
|
||||||
|
import WDEApplication from "../../wde/application.js"
|
||||||
|
import AbstractWebDesktopEnvironment from "../../wde/wde.js"
|
||||||
|
import FinderWindow from "./finder-window.js"
|
||||||
|
|
||||||
|
export default class Finder extends WDEApplication{
|
||||||
|
/** @deprecated */
|
||||||
|
static AppId = "Finder"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {AbstractWebDesktopEnvironment} wde
|
||||||
|
*/
|
||||||
|
constructor(wde){
|
||||||
|
super(wde, "Finder")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string[]} args
|
||||||
|
* @param {import("../../wde/wde.js").runContext} runContext
|
||||||
|
*/
|
||||||
|
async NewWindow(args, runContext){
|
||||||
|
let newFinder = new FinderWindow(this, super.WDE())
|
||||||
|
await newFinder.Init(this, args, runContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string[]} args
|
||||||
|
* @param {import("../../wde/wde.js").runContext} runContext
|
||||||
|
*/
|
||||||
|
async NewView(args, runContext){
|
||||||
|
let newFinderView = new FinderWindow(this, super.WDE())
|
||||||
|
await newFinderView.Init(this, args, runContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
async RenderProperites(path){
|
||||||
|
if (path == null || path ==""){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
path: path
|
||||||
|
})
|
||||||
|
|
||||||
|
const response = await fetch(`/app/${this.AppId}/renderProps?` + params)
|
||||||
|
if (response.status != 200){
|
||||||
|
this.WDE().Alert("Error in render properties widget") //TODO
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
|
||||||
|
let newWindow = this.WDE().Decorat.CreateNewWindow(this.AppId, 350, 500 )
|
||||||
|
newWindow.innerHTML = html
|
||||||
|
newWindow.querySelector("#closeWindowButton").addEventListener('click', () => {
|
||||||
|
// console.log(this.WDE().Decorat())
|
||||||
|
this.WDE().Decorat.CloseWindow(newWindow)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
39
front/src/apps/finder/finder.less
Normal file
39
front/src/apps/finder/finder.less
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
@import "../../theme.less";
|
||||||
|
@import "../../wde/effects.less";
|
||||||
|
|
||||||
|
.finder-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: start;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.finder-content > .tool-bar{
|
||||||
|
width: 100%;
|
||||||
|
min-height: 20px;
|
||||||
|
border-bottom: @eff-border-grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-frame.Focused .tool-bar{
|
||||||
|
border-bottom: 1px solid #000000;
|
||||||
|
box-shadow: @eff-box-shadow-convex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.finder-content > .file-view-container{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
// background-color: #FFFFFF;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
75
front/src/desktop.less
Normal file
75
front/src/desktop.less
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
@import "./wde/primitives.less";
|
||||||
|
@import "./wde/widgets/file-view/file-view.less";
|
||||||
|
@import "./wde/widgets/scrollbar/scrollbar.less";
|
||||||
|
@import "./wde/widgets/button/button.less";
|
||||||
|
// @import "./wde/legacy-ui.less";
|
||||||
|
@import "./wde/widgets/basic-widgets.less";
|
||||||
|
@import "./theme.less";
|
||||||
|
@import "./wde/window-frame.less";
|
||||||
|
@import "./wde/widgets/title-bar/title-bar.less";
|
||||||
|
|
||||||
|
.NoClick {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.Click {
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
// .DragArea
|
||||||
|
|
||||||
|
// *{
|
||||||
|
// font-family: Verdana, Geneva, sans-serif;
|
||||||
|
// font-size: 11px;
|
||||||
|
// font-style: normal;
|
||||||
|
// font-weight:initial;
|
||||||
|
// }
|
||||||
|
|
||||||
|
*::-webkit-scrollbar { /* WebKit */
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body{
|
||||||
|
&:extend(.views-font);
|
||||||
|
// zoom: var(--zoom);
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0px;
|
||||||
|
|
||||||
|
font-size: 11px;
|
||||||
|
|
||||||
|
// font-family: "Geneva";
|
||||||
|
src:url("./fonts/Geneva.woff2");
|
||||||
|
|
||||||
|
/* font: normal 14px Summer Pixel 22, "res/SummerPixel22Regular.ttf"; */
|
||||||
|
-webkit-touch-callout: none; /* iOS Safari */
|
||||||
|
-webkit-user-select: none; /* Safari */
|
||||||
|
-khtml-user-select: none; /* Konqueror HTML */
|
||||||
|
-moz-user-select: none; /* Old versions of Firefox */
|
||||||
|
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||||
|
user-select: none; /* Non-prefixed version, currently
|
||||||
|
supported by Chrome, Edge, Opera and Firefox */
|
||||||
|
touch-action: manipulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
#applications{
|
||||||
|
position: static;
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#windows-layer {
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
/* position: fixed; */
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
|
||||||
|
#desktop-layer{
|
||||||
|
position: fixed;
|
||||||
|
/* margin: 0px; */
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: @col-ceil;
|
||||||
|
}
|
BIN
front/src/fonts/Charcoal.woff2
Normal file
BIN
front/src/fonts/Charcoal.woff2
Normal file
Binary file not shown.
BIN
front/src/fonts/Geneva.woff2
Normal file
BIN
front/src/fonts/Geneva.woff2
Normal file
Binary file not shown.
110
front/src/mobile.less
Normal file
110
front/src/mobile.less
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
@import "./wde/sunboard/sunboard-mobile.less";
|
||||||
|
@import "./theme.less";
|
||||||
|
@import "./wde/effects.less";
|
||||||
|
@import "./wde/widgets/button/button.less";
|
||||||
|
|
||||||
|
@font-face{
|
||||||
|
font-family: "Geneva";
|
||||||
|
src:url("./fonts/Geneva.woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
body{
|
||||||
|
&:extend(.views-font);
|
||||||
|
// zoom: 2;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0px;
|
||||||
|
|
||||||
|
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
/* font: normal 14px Summer Pixel 22, "res/SummerPixel22Regular.ttf"; */
|
||||||
|
-webkit-touch-callout: none; /* iOS Safari */
|
||||||
|
-webkit-user-select: none; /* Safari */
|
||||||
|
-khtml-user-select: none; /* Konqueror HTML */
|
||||||
|
-moz-user-select: none; /* Old versions of Firefox */
|
||||||
|
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||||
|
user-select: none; /* Non-prefixed version, currently
|
||||||
|
supported by Chrome, Edge, Opera and Firefox */
|
||||||
|
touch-action: manipulation;
|
||||||
|
|
||||||
|
background-color: @col-argent;
|
||||||
|
// /* Auto layout */
|
||||||
|
// display: flex;
|
||||||
|
// flex-direction: column;
|
||||||
|
// align-items: flex-start;
|
||||||
|
// justify-content: flex-start;
|
||||||
|
// margin: 32px;
|
||||||
|
|
||||||
|
// background-image:
|
||||||
|
// linear-gradient(45deg, @col-argent 25%, transparent 25%),
|
||||||
|
// linear-gradient(45deg, transparent 75%, @col-argent 75%),
|
||||||
|
// linear-gradient(45deg, transparent 75%, @col-argent 75%),
|
||||||
|
// linear-gradient(45deg, @col-argent 25%, #777777 25%);
|
||||||
|
|
||||||
|
background-size:10px 10px;
|
||||||
|
|
||||||
|
background-position:0 0, 0 0, -5px -5px, 5px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mobile-app-views{
|
||||||
|
position: absolute;
|
||||||
|
// background-color: aqua;
|
||||||
|
inset: 16px;
|
||||||
|
bottom: 100px;
|
||||||
|
|
||||||
|
border-radius: 5px;
|
||||||
|
border: @eff-border-black;
|
||||||
|
box-shadow: @eff-box-shadow-black;
|
||||||
|
background: @col-gainsboro;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls-bar{
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
// background-color: @col-argent;
|
||||||
|
bottom: 0px;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
// padding: 10px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 53px;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-app-view{
|
||||||
|
// background-color: burlywood;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
// position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wde-mobile-button{
|
||||||
|
&:extend(.wde-button);
|
||||||
|
&:active{
|
||||||
|
&:extend(.wde-button:active);
|
||||||
|
}
|
||||||
|
height: 35px;
|
||||||
|
width: 95px;
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
// padding: 10px;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding-right: 5px;
|
||||||
|
// gap: 53px;
|
||||||
|
// align-self: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wde-mobile-button > .icon{
|
||||||
|
|
||||||
|
// width: 8rem;
|
||||||
|
// height: 8rem;
|
||||||
|
}
|
39
front/src/theme.less
Normal file
39
front/src/theme.less
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
@col-ceil: #9999CC;
|
||||||
|
|
||||||
|
@col-argent: #C0C0C0;
|
||||||
|
@col-chinese-silver: #CCCCCC;
|
||||||
|
@col-gainsboro: #DDDDDD;
|
||||||
|
|
||||||
|
@col-bright-grey: #EEEEEE;
|
||||||
|
@col-davys-grey: #555555;
|
||||||
|
@col-granite-gray: #666666;
|
||||||
|
@col-grey: #808080;
|
||||||
|
|
||||||
|
@col-black: #000000;
|
||||||
|
@col-white: #FFFFFF;
|
||||||
|
@col-raisin-black: #222222;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@font-face{
|
||||||
|
font-family: "Geneva";
|
||||||
|
src:url("./fonts/Geneva.woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Charcoal";
|
||||||
|
src: url('./fonts/Charcoal.woff2');
|
||||||
|
}
|
||||||
|
|
||||||
|
.large-system-font{
|
||||||
|
font-family: "Charcoal";
|
||||||
|
// font-weight: bold;
|
||||||
|
letter-spacing: 0.35px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.small-system-font{
|
||||||
|
font-family: "Geneva";
|
||||||
|
}
|
||||||
|
.views-font{
|
||||||
|
font-family: "Geneva";
|
||||||
|
}
|
35
front/src/wde/application.js
Normal file
35
front/src/wde/application.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import AbstractWebDesktopEnvironment from "./wde.js"
|
||||||
|
|
||||||
|
export default class WDEApplication{
|
||||||
|
/** @type {AbstractWebDesktopEnvironment} */
|
||||||
|
#wde
|
||||||
|
/** @type {string} */
|
||||||
|
AppId
|
||||||
|
//TODO types
|
||||||
|
AppManifest
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {AbstractWebDesktopEnvironment} wde
|
||||||
|
*/
|
||||||
|
constructor(wde, AppId, manifest){
|
||||||
|
this.#wde = wde //TODO: Vaidate
|
||||||
|
// console.log(wde)
|
||||||
|
this.AppId = AppId //TODO: Validate
|
||||||
|
this.AppManifest = manifest
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {AbstractWebDesktopEnvironment} */
|
||||||
|
WDE(){
|
||||||
|
return this.#wde
|
||||||
|
}
|
||||||
|
|
||||||
|
async NewWindow(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {Element} */
|
||||||
|
async NewView(){
|
||||||
|
return this.#wde.Decorat.CreateNewView(this.AppId)
|
||||||
|
}
|
||||||
|
}
|
103
front/src/wde/decorat/desktop-decorat.js
Normal file
103
front/src/wde/decorat/desktop-decorat.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
export default class DesktopDecorat{
|
||||||
|
/** @type {Element} */
|
||||||
|
#windowsLayer
|
||||||
|
|
||||||
|
constructor(){
|
||||||
|
this.#windowsLayer = document.body.querySelector('#windows-layer') //TODO Validate if null
|
||||||
|
|
||||||
|
let startDrag = (event) => {
|
||||||
|
let window = event.target.closest('.window-frame')
|
||||||
|
this.bringWindowToFront(window)
|
||||||
|
if (event.target.classList.contains("DragArea")){
|
||||||
|
let xPosInit = event.offsetX
|
||||||
|
let yPosInit = event.offsetY
|
||||||
|
let dragWindow = function(event){
|
||||||
|
window.style.left = `${event.clientX - xPosInit}px`
|
||||||
|
window.style.top = `${event.clientY - yPosInit}px`
|
||||||
|
}
|
||||||
|
let stopDrag = function(){
|
||||||
|
removeEventListener('mousemove', dragWindow)
|
||||||
|
removeEventListener('mouseup', stopDrag)
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListener('mousemove', dragWindow)
|
||||||
|
addEventListener('mouseup', stopDrag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.#windowsLayer.addEventListener('mousedown', startDrag)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} window
|
||||||
|
*/
|
||||||
|
bringWindowToFront(window){ //FIXME
|
||||||
|
let previousWindow = this.#windowsLayer.lastChild
|
||||||
|
if (window == null || window == undefined){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (window != previousWindow){
|
||||||
|
this.#windowsLayer.insertBefore(window, previousWindow.nextSibling)
|
||||||
|
previousWindow.classList.remove("Focused")
|
||||||
|
window.classList.add("Focused")
|
||||||
|
} else {
|
||||||
|
window.classList.add("Focused")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} appId
|
||||||
|
* @param {number} width
|
||||||
|
* @param {number} height
|
||||||
|
* @returns {HTMLElement}
|
||||||
|
*/
|
||||||
|
CreateNewWindow(appId, width, height) {
|
||||||
|
let newWindow = document.createElement("div")
|
||||||
|
newWindow.setAttribute('appid', appId)
|
||||||
|
|
||||||
|
// newWindow.setAttribute("class", "WindowFrame ConvexElement")
|
||||||
|
newWindow.setAttribute("class", "window-frame")
|
||||||
|
newWindow.setAttribute("windowId", this.#makeid(4)) //TODO:
|
||||||
|
|
||||||
|
newWindow.style.width = width.toString() + "px"
|
||||||
|
newWindow.style.height = height.toString() + "px"
|
||||||
|
|
||||||
|
document.body.querySelector('#windows-layer').appendChild(newWindow)
|
||||||
|
return newWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} window
|
||||||
|
*/
|
||||||
|
CloseWindow(window) {
|
||||||
|
window.remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseFocusedWindow() {
|
||||||
|
if (document.body.querySelector('#windows-layer').childElementCount > 1){
|
||||||
|
document.body.querySelector('#windows-layer').lastElementChild.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ChangeURL(appWindow){
|
||||||
|
let appId = appWindow.getAttribute('appid')
|
||||||
|
window.history.replaceState(null, "", `/${appId}/`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {num} length
|
||||||
|
*/
|
||||||
|
#makeid(length) {
|
||||||
|
let result = '';
|
||||||
|
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
|
const charactersLength = characters.length;
|
||||||
|
let counter = 0;
|
||||||
|
while (counter < length) {
|
||||||
|
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
37
front/src/wde/decorat/mobile-decorat.js
Normal file
37
front/src/wde/decorat/mobile-decorat.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
export default class MobileDecorat {
|
||||||
|
/** @type {Element} */
|
||||||
|
#applicationsNode
|
||||||
|
constructor(){
|
||||||
|
this.#applicationsNode = document.body.querySelector("#mobile-app-views") //TODO validate
|
||||||
|
this.#loadControlsBar()
|
||||||
|
}
|
||||||
|
|
||||||
|
#loadControlsBar(){
|
||||||
|
let bar = document.body.querySelector("#controls-bar") //TODO Validate
|
||||||
|
console.log(bar)
|
||||||
|
bar.querySelector("#back").addEventListener('click', () => {
|
||||||
|
this.BackAction()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param {string} appId
|
||||||
|
* @returns {Element}
|
||||||
|
*/
|
||||||
|
CreateNewView(appId){
|
||||||
|
let newView = document.createElement("div")
|
||||||
|
newView.setAttribute("class", "mobile-app-view")
|
||||||
|
newView.setAttribute("appId", appId)
|
||||||
|
// this.#applicationsNode.appendChild(newView)
|
||||||
|
this.#applicationsNode.insertBefore(newView, this.#applicationsNode.firstChild)
|
||||||
|
return newView
|
||||||
|
}
|
||||||
|
|
||||||
|
Open(){
|
||||||
|
|
||||||
|
}
|
||||||
|
BackAction(){
|
||||||
|
console.log(this.#applicationsNode.childNodes.length)
|
||||||
|
if (this.#applicationsNode.childNodes.length <= 1) return
|
||||||
|
this.#applicationsNode.firstChild.remove()
|
||||||
|
}
|
||||||
|
}
|
45
front/src/wde/effects.less
Normal file
45
front/src/wde/effects.less
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
.adjective{
|
||||||
|
border: 1px solid #555555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.convex{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border{
|
||||||
|
.grey{
|
||||||
|
border: 1px solid @col-davys-grey;
|
||||||
|
}
|
||||||
|
.black{
|
||||||
|
border: 1px solid @col-black;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow{ //FIXME: shadow must be 2px offset from windows borders
|
||||||
|
.grey{
|
||||||
|
box-shadow: 1px 1px 0px @col-davys-grey;
|
||||||
|
}
|
||||||
|
.black{
|
||||||
|
box-shadow: 1px 1px 0px @col-black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.rows-fill-shadowed{
|
||||||
|
background: linear-gradient(transparent 0%, white 0%, white 50%, transparent 50%);
|
||||||
|
background-size: 2px 2px;
|
||||||
|
filter: drop-shadow(1px 1px 0px #777777);
|
||||||
|
}
|
||||||
|
@eff-border-black: 1px solid @col-black;
|
||||||
|
@eff-border-grey: 1px solid @col-davys-grey;
|
||||||
|
|
||||||
|
@eff-box-shadow-grey: 1px 1px 0px @col-davys-grey;
|
||||||
|
@eff-box-shadow-black: 1px 1px 0px @col-black;
|
||||||
|
|
||||||
|
@eff-box-shadow-convex: inset -1px -1px 0px rgba(0, 0, 0, 0.27),inset 1px 1px 0px @col-white;
|
||||||
|
@eff-box-shadow-convex-inverted: inset 1px 1px 0px rgba(0, 0, 0, 0.27),inset -1px -1px 0px @col-grey;
|
||||||
|
@eff-box-shadow-adjective: -1px -1px 0px rgba(0, 0, 0, 0.25), 1px 1px 0px #FFFFFF;
|
232
front/src/wde/legacy-ui.less
Normal file
232
front/src/wde/legacy-ui.less
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
// .WindowFrame {
|
||||||
|
// /* Auto layout */
|
||||||
|
// display: flex;
|
||||||
|
// flex-direction: column;
|
||||||
|
// align-items: flex-start;
|
||||||
|
// padding: 4px;
|
||||||
|
// padding-top: 2px;
|
||||||
|
// padding-right: 6px;
|
||||||
|
// gap: 4px;
|
||||||
|
|
||||||
|
// position: absolute;
|
||||||
|
|
||||||
|
// background: #DDDDDD;
|
||||||
|
// border: 1px solid #555555;
|
||||||
|
|
||||||
|
|
||||||
|
// /* Inside auto layout */
|
||||||
|
// flex: none;
|
||||||
|
// order: 1;
|
||||||
|
// align-self: stretch;
|
||||||
|
// flex-grow: 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/* TODO Add shadows to windows */
|
||||||
|
.WindowFrame.Focused{
|
||||||
|
border: 1px solid #000000;
|
||||||
|
background-color: #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrameShadow {
|
||||||
|
box-shadow: 2px 2px 0px #555555;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME Not work on context menu */
|
||||||
|
.WindowFrameShadow.Focused {
|
||||||
|
box-shadow: 2px 2px 0px #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ConvexElement.Focused {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.AdjectiveHorizontalLine:last-child {
|
||||||
|
height: 0%;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.WindowFrame .TitleBar {
|
||||||
|
width: 100%;
|
||||||
|
height: 13px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 0px;
|
||||||
|
|
||||||
|
|
||||||
|
/* Inside auto layout */
|
||||||
|
flex: none;
|
||||||
|
order: 0;
|
||||||
|
align-self: stretch;
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrame .TitleBar .Lable {
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
/* font-size: 13px; */
|
||||||
|
color:#777777;
|
||||||
|
pointer-events: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
font-family: "Virtue";
|
||||||
|
letter-spacing: 0.35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrame.Focused .TitleBar .Lable {
|
||||||
|
color:#000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.WindowFrame .TitleBar .Button {
|
||||||
|
width: 11px;
|
||||||
|
height: 11px;
|
||||||
|
padding: 0%;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
visibility: hidden;
|
||||||
|
|
||||||
|
background: linear-gradient(135deg, #999999 18.18%, #FFFFFF 81.82%);
|
||||||
|
border: 1px solid #222222;
|
||||||
|
box-shadow: 0.5px 0.5px 0px 0.5px #FFFFFF,
|
||||||
|
-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(0, 0, 0, 0.27);
|
||||||
|
/* Inside auto layout */
|
||||||
|
flex: none;
|
||||||
|
order: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrame.Focused .TitleBar .Button {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrame .TitleBar .Button:active {
|
||||||
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
|
/* Green */
|
||||||
|
box-shadow: 0.5px 0.5px 0px 0.5px #FFFFFF,
|
||||||
|
-0.5px -0.5px 0px 0.5px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.Focused .VisualDragArea {
|
||||||
|
pointer-events: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 11px;
|
||||||
|
background: linear-gradient(transparent 0%, white 0%, white 50%, transparent 50%);
|
||||||
|
background-size: 2px 2px;
|
||||||
|
filter: drop-shadow(1px 1px 0px #777777);
|
||||||
|
}
|
||||||
|
|
||||||
|
.MobileContentBorder {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #DDDDDD;
|
||||||
|
/* 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; */
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-x: hidden;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MobileApplicationWindow {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MobileWindowFrameBottomBar {
|
||||||
|
width: 100%;
|
||||||
|
height: 20px;
|
||||||
|
/*
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 0px; */
|
||||||
|
|
||||||
|
/* Inside auto layout */
|
||||||
|
flex: none;
|
||||||
|
order: 0;
|
||||||
|
align-self: stretch;
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MobileWindowFrameBottomBarButton {
|
||||||
|
min-width: 11px;
|
||||||
|
width: auto;
|
||||||
|
height: 15px;
|
||||||
|
padding: 0px 4px 0px 4px;
|
||||||
|
position: absolute;
|
||||||
|
right: 4px;
|
||||||
|
|
||||||
|
background: linear-gradient(135deg, #999999 18.18%, #FFFFFF 81.82%);
|
||||||
|
border: 1px solid #222222;
|
||||||
|
box-shadow: 0.5px 0.5px 0px 0.5px #FFFFFF,
|
||||||
|
-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(0, 0, 0, 0.27);
|
||||||
|
|
||||||
|
/* Inside auto layout */
|
||||||
|
flex: none;
|
||||||
|
order: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MobileWindowFrameBottomBar .MobileLable {
|
||||||
|
position: absolute;
|
||||||
|
/* top:1px; */
|
||||||
|
/* font-size: 13px; */
|
||||||
|
left: 50%;
|
||||||
|
pointer-events: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
font-family: "Virtue";
|
||||||
|
letter-spacing: 0.35px;
|
||||||
|
|
||||||
|
}
|
11
front/src/wde/primitives.less
Normal file
11
front/src/wde/primitives.less
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
.WdePrimitives {
|
||||||
|
|
||||||
|
.adjective{
|
||||||
|
border: 1px solid #555555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.black-border{
|
||||||
|
border: 1px solid #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
49
front/src/wde/sunboard/sunboard-mobile.js
Normal file
49
front/src/wde/sunboard/sunboard-mobile.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import MobileWebDesktopEnvironment from "../wde-mobile.js"
|
||||||
|
|
||||||
|
export default class MobileDesktop{
|
||||||
|
/**@type {Element} */
|
||||||
|
#icons
|
||||||
|
/** @type {MobileWebDesktopEnvironment} */
|
||||||
|
#wde
|
||||||
|
constructor(wde){
|
||||||
|
this.#wde = wde
|
||||||
|
this.load()
|
||||||
|
}
|
||||||
|
|
||||||
|
async load(){
|
||||||
|
let view = this.#createDesktopView()
|
||||||
|
}
|
||||||
|
|
||||||
|
async #createDesktopView(){
|
||||||
|
let view = this.#wde.Decorat.CreateNewView("Sunboard") //FIXME
|
||||||
|
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
// path: args[0] //FIXME
|
||||||
|
path: "/" //FIXME
|
||||||
|
})
|
||||||
|
const response = await fetch(`/app/Sunboard/render?` + params,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
// body: JSON.stringify(runContext)
|
||||||
|
})
|
||||||
|
if (response.status != 200){
|
||||||
|
console.log(response.status)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
view.innerHTML = html
|
||||||
|
|
||||||
|
let iconsList = view.querySelectorAll(".app-icon")
|
||||||
|
iconsList.forEach(element => {
|
||||||
|
let path = element.getAttribute('path') //TODO: Validate
|
||||||
|
|
||||||
|
element.addEventListener('click', () => {
|
||||||
|
this.#wde.Open(path, ["/"], "") //FIXME
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async createFileView(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
62
front/src/wde/sunboard/sunboard-mobile.less
Normal file
62
front/src/wde/sunboard/sunboard-mobile.less
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
@import "../../theme.less";
|
||||||
|
@import "../primitives.less";
|
||||||
|
|
||||||
|
#mobile-sunboard{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
#icons{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
// background-color: @col-ceil;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #down-bar{
|
||||||
|
// &:extend(.WdePrimitives.AdjectiveElement);
|
||||||
|
// width: 100%;
|
||||||
|
// height: 150px;
|
||||||
|
// background-color: @col-argent;
|
||||||
|
// }
|
||||||
|
|
||||||
|
.apps-list{
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
padding: 64px 16px;
|
||||||
|
align-items: flex-start;
|
||||||
|
align-content: flex-start;
|
||||||
|
gap: 64px 0px;
|
||||||
|
flex: 1 0 0;
|
||||||
|
align-self: stretch;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-icon{
|
||||||
|
// background-color: rgba(0, 255, 255, 0.133);
|
||||||
|
width: 100px;
|
||||||
|
// height: 100px;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
// padding: 4px 8px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-icon .icon{
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
// background-color: beige;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-icon .lable{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
144
front/src/wde/wde-desktop.js
Normal file
144
front/src/wde/wde-desktop.js
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
import DesktopDecorat from "./decorat/desktop-decorat.js";
|
||||||
|
import WDEScrollBar from "./widgets/scrollbar/scrollbar.js";
|
||||||
|
import WebFS from "../web-fs/web-fs.js";
|
||||||
|
import WDEApplication from "./application.js";
|
||||||
|
import WDEFileView from "./widgets/file-view/file-view.js";
|
||||||
|
import AbstractWebDesktopEnvironment from "./wde.js";
|
||||||
|
|
||||||
|
// import DesktopSunBoard from "./sunboard/sunboard-desktop.js";
|
||||||
|
export default class WebDesktopEnvironment extends AbstractWebDesktopEnvironment{
|
||||||
|
/** @type {string} */
|
||||||
|
test = ""
|
||||||
|
/** @type {WDEFileView} */
|
||||||
|
FileView = WDEFileView
|
||||||
|
/** @type {WDEScrollBar} */
|
||||||
|
ScrollBar = WDEScrollBar
|
||||||
|
/**@type {DesktopDecorat} */
|
||||||
|
Decorat
|
||||||
|
/** @type {Object<string, WDEApplication>} */
|
||||||
|
static Applications = {};
|
||||||
|
/** @deprecated */
|
||||||
|
static isMobile = false
|
||||||
|
// static decorat
|
||||||
|
static webFs
|
||||||
|
|
||||||
|
/** @deprecated */
|
||||||
|
basicWindow
|
||||||
|
|
||||||
|
constructor(){
|
||||||
|
super("localhost:8080")
|
||||||
|
super._SetWDE(this)
|
||||||
|
document.body.style.setProperty('--zoom', 1)
|
||||||
|
this.Decorat = new DesktopDecorat()
|
||||||
|
|
||||||
|
WebDesktopEnvironment.webFs = new WebFS()
|
||||||
|
this.FileView = WDEFileView
|
||||||
|
this.loadWDE()
|
||||||
|
// this.#devLoadSunboard()
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadWDE(){
|
||||||
|
await this.Open("/Applications/Finder.app", ["/home/user/.Desktop","--desktop", "desktop-layer"])
|
||||||
|
await this.Open("/Applications/Finder.app", ["/", ""])
|
||||||
|
// await this.Open("/Applications/AboutMe.app", [])
|
||||||
|
return
|
||||||
|
|
||||||
|
let autoStart = document.body.querySelector("wde-autostart")
|
||||||
|
if (autoStart == null){
|
||||||
|
WebDesktopEnvironment.Alert("Error in loading DE: Autostart not presented")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for (const child of autoStart.children) {
|
||||||
|
if (child.nodeName != "APP") continue
|
||||||
|
let appPath = child.getAttribute("app-path")
|
||||||
|
if (appPath == null) continue
|
||||||
|
|
||||||
|
let args = []
|
||||||
|
let argsRaw = child.querySelector("args")
|
||||||
|
if (argsRaw == null) continue
|
||||||
|
|
||||||
|
for (const argRaw of argsRaw.children) {
|
||||||
|
let arg = argRaw.getAttribute("string")
|
||||||
|
if (arg == null) continue
|
||||||
|
args.push(arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log(appPath, args)
|
||||||
|
await this.Open(appPath, args)
|
||||||
|
}
|
||||||
|
autoStart.remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} appPath
|
||||||
|
* @param {string[]} args
|
||||||
|
* @param {string} runPath
|
||||||
|
*/
|
||||||
|
async Open(appPath, args, runPath){
|
||||||
|
const runContext = {
|
||||||
|
isMobile: false,
|
||||||
|
bundlePath: appPath,
|
||||||
|
runPath: runPath
|
||||||
|
}
|
||||||
|
|
||||||
|
super._Open(appPath, args, runPath, (appManifest) =>{
|
||||||
|
super._GetApp(appManifest.appId).NewWindow(args, runContext)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* @param {string} html
|
||||||
|
*/
|
||||||
|
static SetBasicWindow(html){
|
||||||
|
this.basicWindow = html
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
static GetBasicWindow(){
|
||||||
|
return this.basicWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} alertText
|
||||||
|
*/
|
||||||
|
Alert(alertText){
|
||||||
|
this.#createAlertWindow(alertText)
|
||||||
|
console.log(alertText)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} alertText
|
||||||
|
*/
|
||||||
|
#createAlertWindow(alertText){
|
||||||
|
let newWindow = document.createElement("div")
|
||||||
|
newWindow.setAttribute("class", "WindowFrameless")
|
||||||
|
newWindow.setAttribute("windowId", "SuperUniqUUID") //TODO:
|
||||||
|
newWindow.style.cssText = "position:absolute;width:450px;height:116px; margin-left: -225px; margin-top:-58px;left: 50%;top: 50%;background-color:#FFFFFF;border: 1px solid #000000;box-shadow: 2px 2px 0px #000000;"
|
||||||
|
|
||||||
|
let alertImage = document.createElement("img")
|
||||||
|
alertImage.setAttribute("src", "/res/sys/wde/icons/ohno.png")
|
||||||
|
alertImage.style.cssText = "position:absolute; width:64px;height:64px;top:15px;left:25px"
|
||||||
|
newWindow.appendChild(alertImage)
|
||||||
|
|
||||||
|
let errorText = document.createElement("div")
|
||||||
|
errorText.style.cssText = "position:absolute; width: 300px; left:128px; top:30px;font-family: 'Virtue';"
|
||||||
|
errorText.innerHTML = alertText
|
||||||
|
newWindow.appendChild(errorText)
|
||||||
|
|
||||||
|
let closeButton = document.createElement("button")
|
||||||
|
closeButton.style.cssText = "position:absolute; left: 382px; bottom: 10px; background-color:#FFFFFF; width: 55px; height:18px; font-family: 'Virtue'; border-radius:4px;border: 1px solid #000000;"
|
||||||
|
closeButton.innerHTML = "Close"
|
||||||
|
closeButton.addEventListener('click', () => { newWindow.remove()})
|
||||||
|
newWindow.appendChild(closeButton)
|
||||||
|
|
||||||
|
document.body.querySelector('#windows-layer').appendChild(newWindow)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
55
front/src/wde/wde-mobile.js
Normal file
55
front/src/wde/wde-mobile.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import MobileDecorat from "./decorat/mobile-decorat.js"
|
||||||
|
import MobileSunboard from "./sunboard/sunboard-mobile.js"
|
||||||
|
import AbstractWebDesktopEnvironment from "./wde.js"
|
||||||
|
import WDEFileView from "./widgets/file-view/file-view.js"
|
||||||
|
export default class MobileWebDesktopEnvironment extends AbstractWebDesktopEnvironment{
|
||||||
|
/** @type {MobileDecorat} */
|
||||||
|
Decorat
|
||||||
|
/** @type {WDEFileView} */
|
||||||
|
FileView
|
||||||
|
/** @type {MobileSunboard} */
|
||||||
|
#sunBoard
|
||||||
|
constructor(){
|
||||||
|
super()
|
||||||
|
super._SetWDE(this)
|
||||||
|
document.body.style.setProperty('--zoom', 3)
|
||||||
|
this.Decorat = new MobileDecorat()
|
||||||
|
this.FileView = WDEFileView
|
||||||
|
this.#sunBoard = new MobileSunboard(this)
|
||||||
|
// this.loadWDE()
|
||||||
|
|
||||||
|
document.addEventListener("touchstart", function(){}, true);//For working :active in css
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
loadWDE(){
|
||||||
|
this.#initControlsBar()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} appPath
|
||||||
|
* @param {string[]} args
|
||||||
|
* @param {string} runPath
|
||||||
|
*/
|
||||||
|
async Open(appPath, args, runPath){
|
||||||
|
const runContext = {
|
||||||
|
isMobile: true,
|
||||||
|
bundlePath: appPath,
|
||||||
|
runPath: runPath
|
||||||
|
}
|
||||||
|
|
||||||
|
super._Open(appPath, args, runPath, (appManifest) =>{
|
||||||
|
// console.log(super._GetApp(appManifest.appId))
|
||||||
|
super._GetApp(appManifest.appId).NewView(args, runContext)
|
||||||
|
}, this)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#initControlsBar(){
|
||||||
|
let barNode = document.body.querySelector("#controls-bar")//TODO Validate
|
||||||
|
|
||||||
|
barNode.querySelector("#back").addEventListener('click', () => {
|
||||||
|
this.Decorat.BackAction()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
116
front/src/wde/wde.js
Normal file
116
front/src/wde/wde.js
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import WDEApplication from "./application.js"
|
||||||
|
import WebFS from "../web-fs/web-fs.js"
|
||||||
|
export default class AbstractWebDesktopEnvironment{
|
||||||
|
/** @type {string} */
|
||||||
|
#apiAddress
|
||||||
|
/** @type {Object<string, WDEApplication>} */
|
||||||
|
_applications = {}
|
||||||
|
/** @type {AbstractWebDesktopEnvironment} */
|
||||||
|
#wde
|
||||||
|
/** @type {WebFS} */
|
||||||
|
#webFS
|
||||||
|
|
||||||
|
/** @constructor */
|
||||||
|
constructor(apiAddress){
|
||||||
|
this.#apiAddress = apiAddress
|
||||||
|
this.#webFS = WebFS
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
GetApiAddress(){
|
||||||
|
return `${location.protocol}//${this.#apiAddress}`
|
||||||
|
}
|
||||||
|
/** @type {AbstractWebDesktopEnvironment} */
|
||||||
|
_SetWDE(wde){
|
||||||
|
this.#wde = wde
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {Object | undefined} //FIXME
|
||||||
|
*/
|
||||||
|
async _FetchAppManifest(path){
|
||||||
|
console.log(path)
|
||||||
|
// console.log(this.GetApiAddress())
|
||||||
|
const params = new URLSearchParams({path: path, mode: "json"})
|
||||||
|
const response = await fetch(`/system/loadApp?` + params)
|
||||||
|
if (response.status != 200){
|
||||||
|
const error = await response.json()
|
||||||
|
// WebDesktopEnvironment.Alert(error.message) //FIXME
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
//TODO Validate manifest
|
||||||
|
const appManifest = response.json()
|
||||||
|
return appManifest
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} appPath
|
||||||
|
* @param {runContext} runContext
|
||||||
|
* @param {string} runPath
|
||||||
|
* @param {function} callback
|
||||||
|
*/
|
||||||
|
async _Open(appPath, runContext, runPath, callback){
|
||||||
|
const appManifest = await this._FetchAppManifest(appPath)
|
||||||
|
|
||||||
|
if (appManifest === undefined) return //TODO return err
|
||||||
|
|
||||||
|
if (this._applications[appManifest.appId] === undefined){
|
||||||
|
this.#loadApp(appManifest, () => {
|
||||||
|
callback(appManifest)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
callback(appManifest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} appManifest
|
||||||
|
* @param {function} onload callback after script loading
|
||||||
|
*/
|
||||||
|
async #loadApp(appManifest, onload){
|
||||||
|
let newApp
|
||||||
|
// console.log(appManifest)
|
||||||
|
await import(appManifest.js[0]).then((app) => {newApp = app}) //FIXME
|
||||||
|
let newAppClass = new newApp.default(this.#wde, appManifest)
|
||||||
|
this._applications[appManifest.appId] = newAppClass
|
||||||
|
|
||||||
|
let cssFile = document.createElement( "link" );
|
||||||
|
cssFile.rel = "stylesheet";
|
||||||
|
cssFile.type = "text/css";
|
||||||
|
cssFile.href = appManifest.css[0];
|
||||||
|
document.head.appendChild( cssFile );
|
||||||
|
|
||||||
|
onload()
|
||||||
|
return //TODO return result
|
||||||
|
}
|
||||||
|
|
||||||
|
_GetApp(appId){
|
||||||
|
// console.log(appId)
|
||||||
|
return this._applications[appId]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {WebFS} */
|
||||||
|
WebFS(){
|
||||||
|
return this.#webFS
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} alertText
|
||||||
|
*/
|
||||||
|
Alert(alertText){}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} runContext
|
||||||
|
* @property {boolean} isMobile
|
||||||
|
* @property {string} appPath
|
||||||
|
* @property {string} runPath //TODO
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** //TODO
|
||||||
|
* @typedef {Object} appManifest
|
||||||
|
*/
|
60
front/src/wde/widgets/basic-widgets.less
Normal file
60
front/src/wde/widgets/basic-widgets.less
Normal 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;
|
||||||
|
}
|
27
front/src/wde/widgets/button/button.less
Normal file
27
front/src/wde/widgets/button/button.less
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
@import "../../effects.less";
|
||||||
|
@import "../../../theme.less";
|
||||||
|
|
||||||
|
.wde-button{
|
||||||
|
&:active{
|
||||||
|
background-color: @col-granite-gray;
|
||||||
|
box-shadow: @eff-box-shadow-convex-inverted;
|
||||||
|
// background-color: red;
|
||||||
|
}
|
||||||
|
background-color: @col-gainsboro;
|
||||||
|
box-shadow: @eff-box-shadow-convex;
|
||||||
|
border: @eff-border-black;
|
||||||
|
border-radius: 3px;
|
||||||
|
|
||||||
|
|
||||||
|
height: 20px;
|
||||||
|
width: auto;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// .wde-button:active{
|
||||||
|
// background-color: red;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .wde-button:hover{
|
||||||
|
// background-color: pink;
|
||||||
|
// }
|
138
front/src/wde/widgets/file-view/file-view.js
Normal file
138
front/src/wde/widgets/file-view/file-view.js
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
import AbstractWebDesktopEnvironment from "../../wde.js"
|
||||||
|
|
||||||
|
|
||||||
|
export default class WDEFileView{
|
||||||
|
path = ""
|
||||||
|
parentElem = undefined
|
||||||
|
selected = []
|
||||||
|
/** @type {AbstractWebDesktopEnvironment} */
|
||||||
|
#wde
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} fileViewElem
|
||||||
|
* @param {Function} doubleClickCallback
|
||||||
|
* @param {Function} rightClickCallback
|
||||||
|
* @param {Function} updateFileViewCallback
|
||||||
|
*/
|
||||||
|
constructor(fileViewElem, doubleClickCallback, rightClickCallback, fileUploadCallback, updateFileViewCallback, wde){
|
||||||
|
this.#wde = wde
|
||||||
|
//TODO check all params
|
||||||
|
this.parentElem = fileViewElem
|
||||||
|
|
||||||
|
fileViewElem.addEventListener('click', (event) => {
|
||||||
|
if (event.target.classList[0] == 'file-view')
|
||||||
|
{
|
||||||
|
this.DeselectAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (event.detail === 1){
|
||||||
|
this.DeselectAll()
|
||||||
|
this.Select([event.target])
|
||||||
|
} else if (event.detail === 2) {
|
||||||
|
doubleClickCallback(event)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
fileViewElem.addEventListener('contextmenu', (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
if (event.target.classList.contains("Tile")){
|
||||||
|
this.DeselectAll()
|
||||||
|
this.Select([event.target])
|
||||||
|
}
|
||||||
|
this.Select([event.target])
|
||||||
|
rightClickCallback(event)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (fileUploadCallback !== undefined) {
|
||||||
|
let counter = 0
|
||||||
|
let draggedElem = undefined
|
||||||
|
|
||||||
|
fileViewElem.addEventListener('dragstart', (event) => {
|
||||||
|
// console.log(event.target)
|
||||||
|
// console.log(this.path)
|
||||||
|
// draggedElem = event.target
|
||||||
|
event.dataTransfer.setData("fileName", event.target.getAttribute("name"))
|
||||||
|
event.dataTransfer.setData("filePath", this.path + "/" + event.target.getAttribute("name"))
|
||||||
|
event.dataTransfer.setData("dropType", "move")
|
||||||
|
// console.log(updateFileViewCallback)
|
||||||
|
// event.dataTransfer.setData("updateCallback", updateFileViewCallback)
|
||||||
|
// event.dataTransfer.setData("fileName", )
|
||||||
|
// console.log(draggedElem)
|
||||||
|
})
|
||||||
|
|
||||||
|
fileViewElem.addEventListener('dragenter', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
counter++
|
||||||
|
fileViewElem.classList.add("DragDropBorder")
|
||||||
|
})
|
||||||
|
|
||||||
|
fileViewElem.addEventListener('dragend', function(event) {
|
||||||
|
// console.log(fileViewElem)
|
||||||
|
event.preventDefault();
|
||||||
|
counter--
|
||||||
|
if (counter === 0){
|
||||||
|
fileViewElem.classList.remove("DragDropBorder")
|
||||||
|
}
|
||||||
|
// updateFileViewCallback()
|
||||||
|
// draggedElem = undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
fileViewElem.addEventListener('dragleave', function(event) {
|
||||||
|
// console.log(fileViewElem)
|
||||||
|
event.preventDefault();
|
||||||
|
counter--
|
||||||
|
if (counter === 0){
|
||||||
|
fileViewElem.classList.remove("DragDropBorder")
|
||||||
|
}
|
||||||
|
// draggedElem = undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
fileViewElem.addEventListener('dragover', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
})
|
||||||
|
|
||||||
|
fileViewElem.addEventListener("drop", (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
fileUploadCallback(event)
|
||||||
|
fileViewElem.classList.remove("DragDropBorder")
|
||||||
|
// updateFileViewCallback()
|
||||||
|
// this.OpenFolder(this.path)
|
||||||
|
// draggedElem = undefined
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {[]Element} elements
|
||||||
|
*/
|
||||||
|
Select(elements){
|
||||||
|
elements.forEach(element => {
|
||||||
|
this.selected.push(element)
|
||||||
|
element.classList.add("Selected")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DeselectAll(){
|
||||||
|
this.selected.forEach(element => {
|
||||||
|
element.classList.remove("Selected")
|
||||||
|
});
|
||||||
|
this.selected = []
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get html of folder by path
|
||||||
|
* @param {string} path
|
||||||
|
*/
|
||||||
|
async OpenFolder(path){
|
||||||
|
this.path = path
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
path: path
|
||||||
|
})
|
||||||
|
const response = await fetch(`/system/wde/widgets/file-tile-view?` + params)
|
||||||
|
if (response.status != 200){
|
||||||
|
//TODO Error text message
|
||||||
|
this.#wde.Alert("Error in render folder view") //TODO
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let html = await response.text()
|
||||||
|
this.parentElem.innerHTML = html
|
||||||
|
}
|
||||||
|
}
|
89
front/src/wde/widgets/file-view/file-view.less
Normal file
89
front/src/wde/widgets/file-view/file-view.less
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
@import "../../../theme.less";
|
||||||
|
.FileTileView{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
// background-color: @col-white;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* FIXME Bug, on desktop mode top ~10 pixel are not active, like margin:10px */
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView.DragDropBorder{
|
||||||
|
box-shadow: inset 0px 0px 0px 4px #9999CC;
|
||||||
|
/* background-color: blue; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView .FlexContainer{
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 50px;
|
||||||
|
row-gap: 20px;
|
||||||
|
/* padding: 15px; Shit fix TODO: */
|
||||||
|
margin: 15px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-content: flex-start;
|
||||||
|
|
||||||
|
/* overflow: scroll; */
|
||||||
|
/* overflow-x: hidden; */
|
||||||
|
scrollbar-width: none; /* Firefox */
|
||||||
|
-ms-overflow-style: none; /* Internet Explorer 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView::-webkit-scrollbar { /* WebKit */
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView .Tile{
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 2px;
|
||||||
|
padding: 0px;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView .Selected{
|
||||||
|
/* inherits: ; */
|
||||||
|
/* background-color: black; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView .Icon{
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
/* background-image: url("./icons/folder.png"); */
|
||||||
|
background-size: cover;
|
||||||
|
|
||||||
|
// image-rendering: optimizeSpeed; /* STOP SMOOTHING, GIVE ME SPEED */
|
||||||
|
// image-rendering: -moz-crisp-edges; /* Firefox */
|
||||||
|
// image-rendering: -o-crisp-edges; /* Opera */
|
||||||
|
// image-rendering: -webkit-optimize-contrast; /* Chrome (and eventually Safari) */
|
||||||
|
// image-rendering: pixelated; /* Universal support since 2021 */
|
||||||
|
// image-rendering: optimize-contrast; /* CSS3 Proposed */
|
||||||
|
// -ms-interpolation-mode: nearest-neighbor; /* IE8+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView .Selected .Icon{
|
||||||
|
filter: brightness(0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView .Lable{
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FileTileView .Selected .Lable{
|
||||||
|
white-space: nowrap;
|
||||||
|
color: white;
|
||||||
|
background-color: black;
|
||||||
|
}
|
54
front/src/wde/widgets/scrollbar/scrollbar.js
Normal file
54
front/src/wde/widgets/scrollbar/scrollbar.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
export default class WdeScrollBar{
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} scrollBarContainer
|
||||||
|
* @param {HTMLElement} content
|
||||||
|
*/
|
||||||
|
constructor(scrollBarContainer, content){
|
||||||
|
let nonNativeScroll = false
|
||||||
|
console.log(scrollBarContainer, content)
|
||||||
|
// let handler = scrollBarContainer.children[0]
|
||||||
|
//TODO On scroll move focus on window?
|
||||||
|
let handler = scrollBarContainer.querySelector(".scroll-element") //TODO Refactor classes
|
||||||
|
// console.log(handler)
|
||||||
|
|
||||||
|
handler.style.height = (content.clientHeight /content.scrollHeight)* handler.parentElement.clientHeight + 'px'
|
||||||
|
|
||||||
|
let max = handler.parentElement.clientHeight - handler.clientHeight
|
||||||
|
let yPosInit = 0
|
||||||
|
|
||||||
|
handler.addEventListener('mousedown', (event) => {
|
||||||
|
nonNativeScroll = true
|
||||||
|
yPosInit = event.clientY - Number(handler.style.top.replace('px','' ))
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', drag);
|
||||||
|
document.addEventListener('mouseup', stop)
|
||||||
|
})
|
||||||
|
|
||||||
|
content.addEventListener('scroll', (event) =>{
|
||||||
|
if (!this.nonNativeScroll){
|
||||||
|
let handlerPathLength = handler.parentElement.clientHeight - handler.clientHeight //TODO recalculate only on resize event
|
||||||
|
let coefficient = (content.scrollHeight - content.clientHeight) /handlerPathLength
|
||||||
|
handler.style.top = content.scrollTop/coefficient + 'px'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function drag() {
|
||||||
|
// console.log(event.clientY - yPosInit, Number(handler.style.top.replace('px','' )))
|
||||||
|
let pos = event.clientY - yPosInit
|
||||||
|
let clampPos = Math.min(Math.max(pos, 0), max)
|
||||||
|
handler.style.top = clampPos + "px";
|
||||||
|
|
||||||
|
let handlerPathLength = handler.parentElement.clientHeight - handler.clientHeight //TODO recalculate only on resize event
|
||||||
|
let coefficient = (content.scrollHeight - content.clientHeight) /handlerPathLength
|
||||||
|
// console.log(clampPos, coefficient, content.clientHeight, clampPos* coefficient)
|
||||||
|
|
||||||
|
content.scrollTop = clampPos* coefficient
|
||||||
|
}
|
||||||
|
function stop() {
|
||||||
|
// console.log("stop")
|
||||||
|
document.removeEventListener('mousemove', drag);
|
||||||
|
document.removeEventListener('mouseup', stop)
|
||||||
|
nonNativeScroll = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
110
front/src/wde/widgets/scrollbar/scrollbar.less
Normal file
110
front/src/wde/widgets/scrollbar/scrollbar.less
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
// .scroller {
|
||||||
|
// overflow-y: scroll;
|
||||||
|
// scrollbar-color: #0A4C95 #C2D2E4;
|
||||||
|
// border-radius: 0px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .scroll-content {
|
||||||
|
// position: relative;
|
||||||
|
// width: 400px;
|
||||||
|
// height: 414px;
|
||||||
|
// top: -17px;
|
||||||
|
// padding: 20px 10px 20px 10px;
|
||||||
|
// overflow-y: auto;
|
||||||
|
// }
|
||||||
|
|
||||||
|
.scrollbar-place{
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
border-left: @eff-border-grey;
|
||||||
|
width: 14px;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
bottom: 0px;
|
||||||
|
right: 0px;
|
||||||
|
width: 14px;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
// background-color: #EEEEEE;
|
||||||
|
|
||||||
|
|
||||||
|
/* Inside auto layout */
|
||||||
|
flex: none;
|
||||||
|
order: 0;
|
||||||
|
align-self: stretch;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Focused .active .scrollbar-place{
|
||||||
|
border-left: @eff-border-black;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-element{
|
||||||
|
position: relative;
|
||||||
|
visibility: hidden;
|
||||||
|
width: 14px;
|
||||||
|
height: 31px;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Focused .active .scroll-element{
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drag-element{
|
||||||
|
pointer-events: none;
|
||||||
|
/* background-color: #0A4C95; */
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
margin-left: -1px;
|
||||||
|
|
||||||
|
background: linear-gradient(transparent 0%,#CCCCFF 0%, #CCCCFF 50%, transparent 50%);
|
||||||
|
background-size: 2px 2px;
|
||||||
|
|
||||||
|
/* TODO white pixels in rows start */
|
||||||
|
filter: drop-shadow(1px 1px 0px #333399);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO to wde css */
|
||||||
|
.ScrollContent {
|
||||||
|
/* width: 100%;
|
||||||
|
height: 100%; */
|
||||||
|
overflow: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
|
scrollbar-width: none; /* Firefox */
|
||||||
|
-ms-overflow-style: none; /* Internet Explorer 10+ */
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
/* display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 0px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ScrollContent::-webkit-scrollbar { /* WebKit */
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
88
front/src/wde/widgets/title-bar/title-bar.less
Normal file
88
front/src/wde/widgets/title-bar/title-bar.less
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
@import "../../effects.less";
|
||||||
|
@import "../../../theme.less";
|
||||||
|
|
||||||
|
.title-bar{
|
||||||
|
width: 100%;
|
||||||
|
height: 13px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 0px;
|
||||||
|
|
||||||
|
|
||||||
|
/* Inside auto layout */
|
||||||
|
flex: none;
|
||||||
|
order: 0;
|
||||||
|
align-self: stretch;
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-bar .lable{
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
/* font-size: 13px; */
|
||||||
|
color: @col-grey;
|
||||||
|
pointer-events: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&:extend(.large-system-font);
|
||||||
|
|
||||||
|
// font-family: "Virtue";
|
||||||
|
// letter-spacing: 0.35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-frame.Focused .title-bar .lable{
|
||||||
|
color: @col-black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-frame.Focused .title-bar .visual-drag-area{
|
||||||
|
&:extend(.rows-fill-shadowed);
|
||||||
|
pointer-events: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-bar > .icon{
|
||||||
|
// background-color: aqua;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.title-bar > .button{
|
||||||
|
width: 11px;
|
||||||
|
height: 11px;
|
||||||
|
padding: 0%;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
visibility: hidden;
|
||||||
|
|
||||||
|
&:active{
|
||||||
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
|
/* Green */
|
||||||
|
box-shadow: 0.5px 0.5px 0px 0.5px #FFFFFF,
|
||||||
|
-0.5px -0.5px 0px 0.5px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
background: linear-gradient(135deg, #999999 18.18%, #FFFFFF 81.82%);
|
||||||
|
border: 1px solid @col-raisin-black;
|
||||||
|
box-shadow: 0.5px 0.5px 0px 0.5px #FFFFFF,
|
||||||
|
-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(0, 0, 0, 0.27);
|
||||||
|
/* Inside auto layout */
|
||||||
|
flex: none;
|
||||||
|
order: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-frame.Focused .title-bar > .button{
|
||||||
|
visibility:visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
// .window-frame.Focused .title-bar > .button:active{
|
||||||
|
// background-color: aqua;
|
||||||
|
// }
|
50
front/src/wde/window-frame.less
Normal file
50
front/src/wde/window-frame.less
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
@import "../theme.less";
|
||||||
|
@import "./effects.less";
|
||||||
|
|
||||||
|
.window-frame{
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
border: @eff-border-grey;
|
||||||
|
box-shadow: @eff-box-shadow-grey;
|
||||||
|
position: absolute;
|
||||||
|
background-color: @col-gainsboro;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 4px;
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-right: 6px;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
/* Inside auto layout */
|
||||||
|
flex: none;
|
||||||
|
order: 1;
|
||||||
|
align-self: stretch;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.window-frame.Focused{
|
||||||
|
background-color: @col-chinese-silver;
|
||||||
|
border: @eff-border-black;
|
||||||
|
box-shadow: @eff-box-shadow-grey, @eff-box-shadow-convex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.content-border{
|
||||||
|
border: @eff-border-grey;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: @col-bright-grey;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Focused .content-border{
|
||||||
|
background-color: @col-gainsboro;
|
||||||
|
border: @eff-border-black;
|
||||||
|
box-shadow: @eff-box-shadow-adjective;
|
||||||
|
}
|
131
front/src/web-fs/web-fs.js
Normal file
131
front/src/web-fs/web-fs.js
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
export default class WebFS{
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
static async CreateDirectory(path){
|
||||||
|
if (path == undefined){
|
||||||
|
WebDesktopEnvironment.Alert("Path is undefined")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
path: `${path}/New Directory`
|
||||||
|
})
|
||||||
|
const response = await fetch(`/system/fs/createDir?` + params)
|
||||||
|
if (response.status != 200){
|
||||||
|
WebDesktopEnvironment.Alert("DIRCTORY CREATION ERROR") //TODO
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
static async DeleteFile(path){
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
path: path
|
||||||
|
})
|
||||||
|
const response = await fetch(`/system/fs/delete?` + params)
|
||||||
|
if (response.status != 200){
|
||||||
|
WebDesktopEnvironment.Alert("DELETE ERROR") //TODO
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
static async MoveFile(sourcePath, targetPath){
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
sourcePath: sourcePath,
|
||||||
|
targetPath: targetPath
|
||||||
|
})
|
||||||
|
const response = await fetch(`/system/fs/move?` + params)
|
||||||
|
if (response.status != 200){
|
||||||
|
// WebDesktopEnvironment.Alert("Move ERROR") //TODO
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} linkPath
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
static async ReadObjectLink(linkPath){
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
linkPath: linkPath,
|
||||||
|
})
|
||||||
|
const response = await fetch(`/system/fs/readObjectLink?` + params)
|
||||||
|
if (response.status != 200){
|
||||||
|
WebDesktopEnvironment.Alert("TODO") //TODO
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
const path = await response.text()
|
||||||
|
//TODO Validate
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} sourcePath
|
||||||
|
* @param {string} linkPath
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
static async CreatePathLink(sourcePath, linkPath){
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
sourcePath: sourcePath,
|
||||||
|
linkPath: linkPath,
|
||||||
|
})
|
||||||
|
const response = await fetch(`/system/fs/createPathLink?` + params)
|
||||||
|
return response.status == 200
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} linkPath
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
static async ReadPathLink(linkPath){
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
linkPath: linkPath,
|
||||||
|
})
|
||||||
|
const response = await fetch(`/system/fs/readPathLink?` + params)
|
||||||
|
if (response.status != 200){
|
||||||
|
WebDesktopEnvironment.Alert("TODO") //TODO
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
// console.log(response)
|
||||||
|
const file = await response.json()
|
||||||
|
//TODO Validate
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {File} file
|
||||||
|
* @param {string} parentPath
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
static async UploadFile(file, parentPath){
|
||||||
|
console.log('here')
|
||||||
|
let formData = new FormData()
|
||||||
|
formData.append("file", file) //FIXME Conn reset
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
parentPath: parentPath,
|
||||||
|
})
|
||||||
|
const response = await fetch(`/system/fs/upload?` + params,
|
||||||
|
{
|
||||||
|
method: "POST", //TODO Change to PUT?
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
console.log(response.status)
|
||||||
|
if (response.status != 201){
|
||||||
|
const error = await response.json()
|
||||||
|
WebDesktopEnvironment.Alert(error.message)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
30
go.mod
30
go.mod
@ -4,29 +4,51 @@ go 1.18
|
|||||||
|
|
||||||
require github.com/gin-gonic/gin v1.9.0
|
require github.com/gin-gonic/gin v1.9.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/aymerick/douceur v0.2.0 // indirect
|
||||||
|
github.com/golang/snappy v0.0.1 // indirect
|
||||||
|
github.com/gorilla/css v1.0.0 // indirect
|
||||||
|
github.com/klauspost/compress v1.13.6 // indirect
|
||||||
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||||
|
github.com/xdg-go/scram v1.1.1 // indirect
|
||||||
|
github.com/xdg-go/stringprep v1.0.3 // indirect
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bytedance/sonic v1.8.0 // indirect
|
github.com/bytedance/sonic v1.8.0 // indirect
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||||
|
github.com/floresj/go-contrib-mobile v0.0.0-20150714204826-47557cfa26f5
|
||||||
|
github.com/gin-contrib/cors v1.4.0
|
||||||
|
github.com/gin-contrib/location v0.0.2
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.11.2 // indirect
|
github.com/go-playground/validator/v10 v10.11.2 // indirect
|
||||||
github.com/goccy/go-json v0.10.0 // indirect
|
github.com/goccy/go-json v0.10.0 // indirect
|
||||||
github.com/google/uuid v1.3.0
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||||
|
github.com/microcosm-cc/bluemonday v1.0.24
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||||
|
github.com/russross/blackfriday v1.6.0
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0
|
||||||
|
github.com/thinkerou/favicon v0.2.0
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.9 // indirect
|
github.com/ugorji/go/codec v1.2.9 // indirect
|
||||||
|
go.mongodb.org/mongo-driver v1.11.6
|
||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
|
||||||
golang.org/x/crypto v0.5.0 // indirect
|
golang.org/x/crypto v0.5.0 // indirect
|
||||||
golang.org/x/net v0.7.0 // indirect
|
golang.org/x/net v0.10.0 // indirect
|
||||||
golang.org/x/sys v0.5.0 // indirect
|
golang.org/x/sys v0.8.0 // indirect
|
||||||
golang.org/x/text v0.7.0 // indirect
|
golang.org/x/text v0.9.0 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
123
go.sum
123
go.sum
@ -1,73 +1,180 @@
|
|||||||
|
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||||
|
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||||
github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
|
github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
|
||||||
github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/floresj/go-contrib-mobile v0.0.0-20150714204826-47557cfa26f5 h1:e+OSfbvxkjub+bPlfDmqENiV9IEOnLUk9TU7fMhu2Ks=
|
||||||
|
github.com/floresj/go-contrib-mobile v0.0.0-20150714204826-47557cfa26f5/go.mod h1:2F+cddOTo8Rjp/98JPjMwZRCcCA1dP1VeNBvfk/tU6I=
|
||||||
|
github.com/gin-contrib/cors v1.4.0 h1:oJ6gwtUl3lqV0WEIwM/LxPF1QZ5qe2lGWdY2+bz7y0g=
|
||||||
|
github.com/gin-contrib/cors v1.4.0/go.mod h1:bs9pNM0x/UsmHPBWT2xZz9ROh8xYjYkiURUfmBoMlcs=
|
||||||
|
github.com/gin-contrib/location v0.0.2 h1:QZKh1+K/LLR4KG/61eIO3b7MLuKi8tytQhV6texLgP4=
|
||||||
|
github.com/gin-contrib/location v0.0.2/go.mod h1:NGoidiRlf0BlA/VKSVp+g3cuSMeTmip/63PhEjRhUAc=
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
|
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||||
|
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
|
||||||
github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8=
|
github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8=
|
||||||
github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k=
|
github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k=
|
||||||
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
|
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||||
|
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
|
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||||
|
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
|
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||||
|
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||||
github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
|
github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
|
||||||
github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
|
github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
|
||||||
|
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
|
github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
|
||||||
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
|
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||||
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||||
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
||||||
|
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||||
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/microcosm-cc/bluemonday v1.0.24 h1:NGQoPtwGVcbGkKfvyYk1yRqknzBuoMiUrO6R7uFTPlw=
|
||||||
|
github.com/microcosm-cc/bluemonday v1.0.24/go.mod h1:ArQySAMps0790cHSkdPEJ7bGkF2VePWH773hsJNSHf8=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
||||||
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||||
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
|
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||||
|
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||||
|
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
|
||||||
|
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
github.com/thinkerou/favicon v0.2.0 h1:/qO//fFevzhx68pAAPjuiOwB2ykoKwLcZW9luMZ8PEU=
|
||||||
|
github.com/thinkerou/favicon v0.2.0/go.mod h1:PM31DMRkXDVi9/sGwb/a/evMB536N9VfVNC+Dtf4iDQ=
|
||||||
|
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||||
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
|
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||||
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
|
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||||
github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
|
github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
|
||||||
github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||||
|
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
|
||||||
|
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||||
|
github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs=
|
||||||
|
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||||
|
go.mongodb.org/mongo-driver v1.11.6 h1:XM7G6PjiGAO5betLF13BIa5TlLUUE3uJ/2Ox3Lz1K+o=
|
||||||
|
go.mongodb.org/mongo-driver v1.11.6/go.mod h1:G9TgswdsWjX4tmDA5zfs2+6AEPpYJwqblyjsfuh8oXY=
|
||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
|
||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
||||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||||
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||||
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
|
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
|
BIN
icons/genericApp/color/16.png
(Stored with Git LFS)
Normal file
BIN
icons/genericApp/color/16.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
icons/genericApp/color/32.png
(Stored with Git LFS)
Normal file
BIN
icons/genericApp/color/32.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
icons/genericDocument/color/16.png
(Stored with Git LFS)
Normal file
BIN
icons/genericDocument/color/16.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
icons/genericDocument/color/32.png
(Stored with Git LFS)
Normal file
BIN
icons/genericDocument/color/32.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
icons/genericFolder/color/16.png
(Stored with Git LFS)
Normal file
BIN
icons/genericFolder/color/16.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
icons/genericFolder/color/32.png
(Stored with Git LFS)
Normal file
BIN
icons/genericFolder/color/32.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
icons/github/color/favicon.ico
Normal file
BIN
icons/github/color/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
BIN
icons/github/color/github.png
(Stored with Git LFS)
Normal file
BIN
icons/github/color/github.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
icons/hand/color/8.png
(Stored with Git LFS)
Normal file
BIN
icons/hand/color/8.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
icons/twitter/color/favicon.ico
Normal file
BIN
icons/twitter/color/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
icons/twitter/color/twitter.png
(Stored with Git LFS)
Normal file
BIN
icons/twitter/color/twitter.png
(Stored with Git LFS)
Normal file
Binary file not shown.
64
libs/cat.go
Normal file
64
libs/cat.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package libs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"personalwebsite/webfilesystem"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
//TODO Use this to get json from back
|
||||||
|
type Cat struct {
|
||||||
|
fs *webfilesystem.WebFileSystem
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCatLib(webfs *webfilesystem.WebFileSystem) *Cat {
|
||||||
|
return &Cat{
|
||||||
|
fs: webfs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cat) Get(filePath string) (string, error) {
|
||||||
|
file, err := c.fs.Read(filePath, nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if file.Type != "plaintext" {
|
||||||
|
return "", errors.New("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
fileData := webfilesystem.PlainTextFileData{}
|
||||||
|
_, err = c.fs.Read(filePath, &fileData)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileData.Data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cat) PublicRoutes(route *gin.RouterGroup) {
|
||||||
|
route.GET("get", func(ctx *gin.Context) {
|
||||||
|
path := ctx.Query("path")
|
||||||
|
if path == "" {
|
||||||
|
ctx.String(http.StatusBadRequest, "TODO") //TODO json error struct
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := c.Get(path)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Status(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mode := ctx.Query("mode")
|
||||||
|
switch mode {
|
||||||
|
case "json":
|
||||||
|
ctx.JSON(http.StatusOK, data)
|
||||||
|
default:
|
||||||
|
ctx.String(http.StatusOK, "plaintext", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
79
libs/imglib.go
Normal file
79
libs/imglib.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package libs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"path"
|
||||||
|
"personalwebsite/webfilesystem"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ImagLib struct {
|
||||||
|
fs *webfilesystem.WebFileSystem
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewImgLib(webfs *webfilesystem.WebFileSystem) *ImagLib {
|
||||||
|
return &ImagLib{
|
||||||
|
fs: webfs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ImagLib) PublicRoutes(route *gin.RouterGroup) {
|
||||||
|
route.GET("get", func(ctx *gin.Context) {
|
||||||
|
path := ctx.Query("path")
|
||||||
|
if path == "" {
|
||||||
|
ctx.String(http.StatusBadRequest, "TODO") //TODO json error struct
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
imgData := Img{}
|
||||||
|
_, err := l.fs.Read(path, &imgData)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Status(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Data(http.StatusOK, "image/jpeg", imgData.Bin)
|
||||||
|
})
|
||||||
|
|
||||||
|
iconGroup := route.Group("icon")
|
||||||
|
iconGroup.GET("get", func(ctx *gin.Context) {
|
||||||
|
iconPath := ctx.Query("path")
|
||||||
|
iconType := ctx.Query("type")
|
||||||
|
_ = iconType
|
||||||
|
iconSize := ctx.Query("size")
|
||||||
|
|
||||||
|
imgData := Img{}
|
||||||
|
_, err := l.fs.Read(path.Join(iconPath, "color", iconSize+".png"), &imgData)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Status(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Data(http.StatusOK, "image/jpeg", imgData.Bin)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBase64Image(img *Base64Img, min string) (string, error) {
|
||||||
|
imgString := ""
|
||||||
|
switch min {
|
||||||
|
case "min32":
|
||||||
|
imgString = "data:" + img.Header + ", " + img.Base64Miniature32
|
||||||
|
default:
|
||||||
|
imgString = "data:" + img.Header + ", " + img.Base64
|
||||||
|
}
|
||||||
|
|
||||||
|
return imgString, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Base64Img struct {
|
||||||
|
Header string `bson:"header"`
|
||||||
|
Base64 string `bson:"base64"`
|
||||||
|
Base64Miniature32 string `bson:"base64min32"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Img struct {
|
||||||
|
Header string `bson:"header"`
|
||||||
|
Bin []byte `bson:"bin"`
|
||||||
|
// BinMin32 []byte `bson:"binmin32"`
|
||||||
|
}
|
17
libs/libs.go
Normal file
17
libs/libs.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package libs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"personalwebsite/webfilesystem"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Libs struct {
|
||||||
|
Imglib *ImagLib
|
||||||
|
Cat *Cat
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLibs(webfs *webfilesystem.WebFileSystem) Libs {
|
||||||
|
return Libs{
|
||||||
|
Imglib: NewImgLib(webfs),
|
||||||
|
Cat: NewCatLib(webfs),
|
||||||
|
}
|
||||||
|
}
|
31
libs/markdown.go
Normal file
31
libs/markdown.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package libs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/microcosm-cc/bluemonday"
|
||||||
|
"github.com/russross/blackfriday/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MarkdownLib struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ml *MarkdownLib) Render(md []byte, supressParagraph bool) template.HTML {
|
||||||
|
output := blackfriday.Run(md)
|
||||||
|
if supressParagraph {
|
||||||
|
output = []byte(strings.ReplaceAll(string(output), "<p>", ""))
|
||||||
|
output = []byte(strings.ReplaceAll(string(output), "</p>", ""))
|
||||||
|
}
|
||||||
|
_ = output
|
||||||
|
html := bluemonday.UGCPolicy().SanitizeBytes(output)
|
||||||
|
// println(string(html))
|
||||||
|
kek := template.HTML(html)
|
||||||
|
return kek
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (ml MarkdownLib) MarkDowner(args ...interface{}) template.HTML {
|
||||||
|
// s := blackfriday.MarkdownCommon([]byte(fmt.Sprintf("%s", args...)))
|
||||||
|
|
||||||
|
// return template.HTML(s)
|
||||||
|
// }
|
186
main.go
186
main.go
@ -1,118 +1,100 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"os"
|
||||||
"personalwebsite/routewde"
|
|
||||||
"personalwebsite/websiteapp"
|
|
||||||
"personalwebsite/websiteapp/finder"
|
|
||||||
"personalwebsite/websiteapp/personalprops"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"personalwebsite/apps"
|
||||||
|
blogwriter "personalwebsite/apps/BlogWriter"
|
||||||
|
"personalwebsite/apps/aboutme"
|
||||||
|
"personalwebsite/apps/blogviewer"
|
||||||
|
"personalwebsite/apps/finder"
|
||||||
|
imgviewer "personalwebsite/apps/img-viewer"
|
||||||
|
"personalwebsite/apps/sunboard"
|
||||||
|
"personalwebsite/routes"
|
||||||
|
"personalwebsite/wde"
|
||||||
|
"personalwebsite/webfilesystem"
|
||||||
|
|
||||||
|
"github.com/joho/godotenv"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
)
|
)
|
||||||
|
|
||||||
// func main() {
|
|
||||||
// router := gin.Default()
|
|
||||||
// router.LoadHTMLGlob("templates/**/*")
|
|
||||||
// router.GET("/posts/index", func(c *gin.Context) {
|
|
||||||
// c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{
|
|
||||||
// "title": "Posts",
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// router.GET("/users/index", func(c *gin.Context) {
|
|
||||||
// c.HTML(http.StatusOK, "users/index.tmpl", gin.H{
|
|
||||||
// "title": "Users",
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// router.Run(":8080")
|
|
||||||
// }
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
router := gin.New()
|
if err := godotenv.Load(); err != nil {
|
||||||
|
println("No .env file found")
|
||||||
router.LoadHTMLGlob("templates/**/*")
|
|
||||||
router.Static("/res", "resources")
|
|
||||||
|
|
||||||
router.GET("/", func(ctx *gin.Context) {
|
|
||||||
ctx.HTML(http.StatusOK, "index.tmpl", gin.H{})
|
|
||||||
})
|
|
||||||
|
|
||||||
persPropsApp := personalprops.NewPersPropsApp()
|
|
||||||
finderApp := finder.FinerApplication{}
|
|
||||||
appsStorage := websiteapp.ApplicationsStorage{
|
|
||||||
Apps: map[string]websiteapp.WebDEApplication{},
|
|
||||||
}
|
|
||||||
appsStorage.Apps["personal-properties"] = &persPropsApp
|
|
||||||
appsStorage.Apps["finder"] = &finderApp
|
|
||||||
system := router.Group("system")
|
|
||||||
{
|
|
||||||
|
|
||||||
wde := system.Group("wde")
|
|
||||||
{
|
|
||||||
routewde.Route(wde)
|
|
||||||
}
|
|
||||||
apps := system.Group("applications")
|
|
||||||
{
|
|
||||||
apps.GET("/:appid/:method", func(ctx *gin.Context) {
|
|
||||||
appId := ctx.Param("appid")
|
|
||||||
method := ctx.Param("method")
|
|
||||||
|
|
||||||
app, isExist := appsStorage.Apps[appId]
|
|
||||||
if !isExist {
|
|
||||||
ctx.Status(http.StatusNoContent)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch method {
|
|
||||||
case "getmanifest":
|
|
||||||
ctx.JSON(http.StatusOK, app.GetManifest())
|
|
||||||
case "app.js":
|
|
||||||
ctx.File("resources/sys/" + appId + "/" + appId + ".js")
|
|
||||||
case "app.css":
|
|
||||||
ctx.File("resources/sys/" + appId + "/" + appId + ".css")
|
|
||||||
default:
|
|
||||||
ctx.Status(http.StatusBadRequest)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
websiteapp.Route(apps.Group("/storage"), &appsStorage)
|
|
||||||
// personalpropsroute.Route(apps.Group("/personalproperties"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app := router.Group("application")
|
mongoConnect, err := FindEnv("MONGO_CONNECT")
|
||||||
{
|
if err != nil {
|
||||||
app.GET("test", func(ctx *gin.Context) {
|
panic(err.Error())
|
||||||
ctx.Status(http.StatusOK)
|
|
||||||
})
|
|
||||||
persPropApp := app.Group("personal-properties")
|
|
||||||
{
|
|
||||||
persPropApp.GET("render", func(ctx *gin.Context) {
|
|
||||||
ctx.HTML(http.StatusOK, "personal-properties/app.tmpl", persPropsApp.Render())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
finderAppRoute := app.Group("finder")
|
|
||||||
{
|
|
||||||
finderAppRoute.GET("render", func(ctx *gin.Context) {
|
|
||||||
ctx.HTML(http.StatusOK, "finder/app.tmpl", finderApp.Render())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
router.GET("/test", func(ctx *gin.Context) {
|
|
||||||
ctx.HTML(200, "kek/kek.tmpl", gin.H{})
|
|
||||||
})
|
|
||||||
// router.GET("/room/:roomid", roomGET)
|
|
||||||
// router.POST("/room-post/:roomid", roomPOST)
|
|
||||||
// router.GET("/stream/:roomid", streamRoom)
|
|
||||||
|
|
||||||
// port := os.Getenv("PORT")
|
dBName, err := FindEnv("DATABASE")
|
||||||
// if port == "" {
|
if err != nil {
|
||||||
// port = "8080"
|
panic(err.Error())
|
||||||
// }
|
|
||||||
if err := router.Run(":8080"); err != nil {
|
|
||||||
log.Panicf("error: %s", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
webFsCollection, err := FindEnv("COLLECTION_WEBFS")
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
publicPort, err := FindEnv("PUBLIC_PORT")
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
privatePort, err := FindEnv("PRIVATE_PORT")
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
clientOptions := options.Client().ApplyURI(mongoConnect)
|
||||||
|
client, err := mongo.Connect(context.TODO(), clientOptions)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
err = client.Ping(context.TODO(), nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
webfs := webfilesystem.NewWebFileSystem(client, dBName, webFsCollection)
|
||||||
|
appsStorage := apps.NewApplicationsStorage(map[string]apps.WebDEApplication{}, webfs)
|
||||||
|
|
||||||
|
webde := wde.NewWDE(webfs)
|
||||||
|
|
||||||
|
//TODO Split to different apps init for private and public?
|
||||||
|
persPropsApp := aboutme.NewAboutMeApp(webfs)
|
||||||
|
finderApp := finder.NewFinderApplication(webfs)
|
||||||
|
imgViewerApp := imgviewer.NewImgViewerApp(webfs)
|
||||||
|
blogViewerApp := blogviewer.NewBlogViewerApp(webfs)
|
||||||
|
blogWriterApp := blogwriter.NewBlogWriterApp(webfs)
|
||||||
|
sunBoardApp := sunboard.NewSunboardApp(webfs, webde, appsStorage)
|
||||||
|
|
||||||
|
appsStorage.Apps["personal-properties"] = persPropsApp
|
||||||
|
appsStorage.Apps["finder"] = finderApp
|
||||||
|
appsStorage.Apps["img-viewer"] = imgViewerApp
|
||||||
|
appsStorage.Apps[blogViewerApp.GetAppID()] = blogViewerApp
|
||||||
|
appsStorage.Apps["BlogWriter"] = blogWriterApp
|
||||||
|
appsStorage.Apps["Sunboard"] = sunBoardApp
|
||||||
|
|
||||||
|
go routes.PublicRoutes(publicPort, webfs, webde, appsStorage)
|
||||||
|
routes.PrivateRoutes(privatePort, webfs, webde, appsStorage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func index(c *gin.Context) {
|
// TODO to for loop with aal vars in slice
|
||||||
c.HTML(http.StatusOK, "base.html", nil)
|
func FindEnv(parameter string) (string, error) {
|
||||||
|
path, exists := os.LookupEnv(parameter)
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
println("[ENV] Requsted " + parameter + " = " + path) //FIXME Only in Debug log
|
||||||
|
return path, nil
|
||||||
|
} else {
|
||||||
|
panic("[ENV] Requsted " + parameter + " not found")
|
||||||
|
return "", errors.New("env parameter not found")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<div id="WindowsLayer"></div>
|
<div id="WindowsLayer"></div>
|
||||||
<div id="Applications"></div>
|
<div id="Applications"></div>
|
||||||
<!-- <div id="TestWindow" style="width: 100px; height: 100px; background-color: darkkhaki; position: absolute;" >
|
<!-- <div id="TestWindow" style="width: 100px; height: 100px; background-color: darkkhaki; position: absolute;" >
|
||||||
<div id="TestWindowHeader" class="WindowDragArea" style="width: 100%;height: 15px; background-color: cornflowerblue;">
|
<div id="TestWindowHeader" class="VisualDragArea" style="width: 100%;height: 15px; background-color: cornflowerblue;">
|
||||||
</div> -->
|
</div> -->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
<div id="WindowBorder" class="Frame">
|
<div id="WindowBorder" class="Frame">
|
||||||
<div id="TestWindowHeader" class="WindowFrameTopBar">
|
<div id="TestWindowHeader" class="WindowFrameTopBar">
|
||||||
<button class="WindowFrameTopBarButton"></button>
|
<button class="WindowFrameTopBarButton"></button>
|
||||||
<div id="Drag" class="WindowDragArea"></div>
|
<div id="Drag" class="VisualDragArea"></div>
|
||||||
<div class="WindowFrameTitle">
|
<div class="Lable">
|
||||||
Test Title
|
Test Title
|
||||||
</div>
|
</div>
|
||||||
<div id="Drag" class="WindowDragArea"></div>
|
<div id="Drag" class="VisualDragArea"></div>
|
||||||
<button class="WindowFrameTopBarButton" ></button>
|
<button class="WindowFrameTopBarButton" ></button>
|
||||||
</div>
|
</div>
|
||||||
<div id="ContentFrame" class="ContentFrame">
|
<div id="ContentFrame" class="ContentFrame">
|
||||||
|
37
res/dev-fs/apps/AboutMe/AboutMe.js
Normal file
37
res/dev-fs/apps/AboutMe/AboutMe.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
class AboutMe{
|
||||||
|
static appID = "AboutMe"
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} appElem
|
||||||
|
*/
|
||||||
|
constructor(appElem){
|
||||||
|
this.appElem = appElem
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {[]string} args
|
||||||
|
* @param {Object} runContext
|
||||||
|
*/
|
||||||
|
async NewWindow(args, runContext){
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
path: `:/aboutme.props`,
|
||||||
|
})
|
||||||
|
const response = await fetch(`/app/${AboutMe.appID}/render?`+ params,{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(runContext)
|
||||||
|
})
|
||||||
|
if (response.status != 200){
|
||||||
|
WebDesktopEnvironment.Alert("Error TODO") //TODO
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
|
||||||
|
let newWindow = WebDesktopEnvironment.CreateNewWindow(this.appId, 360, document.body.clientHeight*0.8 )
|
||||||
|
|
||||||
|
newWindow.innerHTML = html
|
||||||
|
newWindow.style.height = 'auto'
|
||||||
|
|
||||||
|
newWindow.querySelector("#closeWindowButton").addEventListener('click', () => {
|
||||||
|
WebDesktopEnvironment.CloseWindow(newWindow)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,32 @@
|
|||||||
.ScrollContent {
|
/* TODO Move this to body? */
|
||||||
|
/*.ScrollContent {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
scrollbar-width: none; /* Firefox */
|
/* Firefox */
|
||||||
-ms-overflow-style: none; /* Internet Explorer 10+ */
|
/* scrollbar-width: none; */
|
||||||
|
/* Internet Explorer 10+ */
|
||||||
|
/* -ms-overflow-style: none; */
|
||||||
|
|
||||||
/* Auto layout */
|
/* Auto layout */
|
||||||
|
/*display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 0px;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/* WebKit */
|
||||||
|
/* .ScrollContent::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
} */
|
||||||
|
.PersPropsContent{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -14,11 +34,11 @@
|
|||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ScrollContent::-webkit-scrollbar { /* WebKit */
|
.PersPropsContent .PropsView{
|
||||||
width: 0;
|
/* background-color: rebeccapurple; */
|
||||||
height: 0;
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.PropertiesList{
|
.PropertiesList{
|
||||||
/* width: 100%;
|
/* width: 100%;
|
||||||
height: auto; */
|
height: auto; */
|
||||||
@ -37,7 +57,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.Personal-properties-bio{
|
.PropertiesList .ShortBio{
|
||||||
/* width: 100%;
|
/* width: 100%;
|
||||||
height: auto; */
|
height: auto; */
|
||||||
/* margin-right: -20px; */
|
/* margin-right: -20px; */
|
||||||
@ -57,9 +77,13 @@
|
|||||||
gap:15px;
|
gap:15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ShortBio .Image{
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ShortBio .Text{
|
||||||
.Personal-properties-textbio{
|
|
||||||
/* width: 100%;
|
/* width: 100%;
|
||||||
height: auto; */
|
height: auto; */
|
||||||
|
|
||||||
@ -77,8 +101,35 @@
|
|||||||
gap:1px;
|
gap:1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ShortBio .Name{
|
||||||
|
font-family: "Virtue";
|
||||||
|
/* FIXME */
|
||||||
|
letter-spacing: 0.35px;
|
||||||
|
}
|
||||||
|
|
||||||
.Personal-properties-prop{
|
.PropertiesList .Links {
|
||||||
|
position: absolute;
|
||||||
|
right: 14px;
|
||||||
|
top: 27px;
|
||||||
|
/* background-color: aqua; */
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: left;
|
||||||
|
padding: 0px;
|
||||||
|
gap:4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PropertiesList .Links .Link {
|
||||||
|
/* background-color:brown; */
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PropertiesList .Island{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
border: 1px solid #888888;
|
border: 1px solid #888888;
|
||||||
@ -93,11 +144,9 @@
|
|||||||
gap:1px; */
|
gap:1px; */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Island .Title {
|
||||||
|
|
||||||
|
|
||||||
.Personal-properties-prop-title{
|
|
||||||
font-family: "Virtue";
|
font-family: "Virtue";
|
||||||
|
/* FIXME */
|
||||||
letter-spacing: 0.35px;
|
letter-spacing: 0.35px;
|
||||||
position:relative;
|
position:relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -107,7 +156,11 @@
|
|||||||
top: -9px;
|
top: -9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Personal-properties-prop-content{
|
.Focused .Island .Title{
|
||||||
|
background-color: #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Island .Content{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
/* top: 0px; */
|
/* top: 0px; */
|
||||||
/* Auto layout */
|
/* Auto layout */
|
||||||
@ -118,7 +171,7 @@
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Personal-properties-prop-row{
|
.Island .Row{
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
/* Auto layout */
|
/* Auto layout */
|
||||||
@ -128,7 +181,7 @@
|
|||||||
padding: 0px;
|
padding: 0px;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
}
|
}
|
||||||
.Personal-properties-prop-key{
|
.Island .Key{
|
||||||
position: relative;
|
position: relative;
|
||||||
font-family: "Virtue";
|
font-family: "Virtue";
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
@ -141,7 +194,7 @@
|
|||||||
/* font-weight: bold; */
|
/* font-weight: bold; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.Personal-properties-prop-key-comments{
|
.Island .KeyComment{
|
||||||
/* color: rgb(129, 129, 129); TODO*/
|
/* color: rgb(129, 129, 129); TODO*/
|
||||||
color: #646464;
|
color: #646464;
|
||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
@ -150,7 +203,8 @@
|
|||||||
white-space:normal;
|
white-space:normal;
|
||||||
/* filter: drop-shadow(-.5px -.5px 0px #616161); */
|
/* filter: drop-shadow(-.5px -.5px 0px #616161); */
|
||||||
}
|
}
|
||||||
.Personal-properties-prop-values{
|
|
||||||
|
.Island .Values{
|
||||||
width: 55%;
|
width: 55%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -160,7 +214,7 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.Personal-properties-prop-value{
|
.Values .Value{
|
||||||
/* width: 55%; */
|
/* width: 55%; */
|
||||||
|
|
||||||
}
|
}
|
51
res/dev-fs/apps/BlogViewer/BlogViewer.js
Normal file
51
res/dev-fs/apps/BlogViewer/BlogViewer.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
class BlogViewer{
|
||||||
|
static appID = "BlogViewer"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string[]} args
|
||||||
|
* @param {Object} runContext
|
||||||
|
*/
|
||||||
|
async NewWindow(args, runContext){
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
path: args[0],
|
||||||
|
})
|
||||||
|
runContext.runPath = args[0]
|
||||||
|
const response = await fetch(`app/${BlogViewer.appID}/render?` + params, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(runContext)
|
||||||
|
})
|
||||||
|
if (response.status != 200){
|
||||||
|
WebDesktopEnvironment.Alert("Error render TODO") //TODO
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
|
||||||
|
let newWindow = WebDesktopEnvironment.CreateNewWindow(this.appId, 500, 350 )
|
||||||
|
newWindow.innerHTML = html
|
||||||
|
|
||||||
|
let scrollBar = new WdeScrollBar(newWindow.querySelector(".ScrollbarPlace"), newWindow.querySelector(".ScrollContent"))
|
||||||
|
newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) {
|
||||||
|
WebDesktopEnvironment.CloseWindow(newWindow)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MouseEvent} event
|
||||||
|
* @param {string} path
|
||||||
|
*/
|
||||||
|
static Click(event, path){
|
||||||
|
let fileType = event.target.getAttribute("fileType")
|
||||||
|
switch (fileType) {
|
||||||
|
case "app":
|
||||||
|
//TODO get real id
|
||||||
|
WebDesktopEnvironment.Open("personal-properties", [])
|
||||||
|
break;
|
||||||
|
case "img":
|
||||||
|
WebDesktopEnvironment.Open("img-viewer", ["pizda"])
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log("Unsupported file type")
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
85
res/dev-fs/apps/BlogViewer/blog-viewer.css
Normal file
85
res/dev-fs/apps/BlogViewer/blog-viewer.css
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
.BlogView{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
/* gap: 50px; */
|
||||||
|
/* row-gap: 20px; */
|
||||||
|
/* padding: 0px 20px 0px 20px; */
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.BlogView .Content {
|
||||||
|
overflow: scroll;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
/* gap: 50px; */
|
||||||
|
/* row-gap: 20px; */
|
||||||
|
/* padding: 0px 20px 0px 20px; */
|
||||||
|
/* margin: 0px 20px 0px 20px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.BlogView .ScrollContent {
|
||||||
|
position: relative;
|
||||||
|
width: 92%;
|
||||||
|
left: 4%;
|
||||||
|
right: 4%;
|
||||||
|
height: auto;
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 10px;
|
||||||
|
/* row-gap: 20px; */
|
||||||
|
/* padding: 0px 20px 0px 20px; */
|
||||||
|
/* margin: 0px 20px 0px 20px; */
|
||||||
|
/* padding-left: 20px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.BlogView .header-h1{
|
||||||
|
font-size:x-large;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.BlogView .header-h2{
|
||||||
|
font-size:large;
|
||||||
|
padding-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.BlogView .header-h3{
|
||||||
|
font-size:larger;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.BlogView .image{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image .ImageProp{
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
/* left: 50%;
|
||||||
|
margin-left: -50%; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.BlogView .plain-text{
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 5px;
|
||||||
|
/* row-gap: 20px; */
|
||||||
|
}
|
10
res/dev-fs/apps/BlogWriter/BlogWriter.js
Normal file
10
res/dev-fs/apps/BlogWriter/BlogWriter.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
class BlogWriter{
|
||||||
|
static AppId = "BlogWriter"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string[]} args
|
||||||
|
*/
|
||||||
|
async NewWindow(args){
|
||||||
|
console.log("kek")
|
||||||
|
}
|
||||||
|
}
|
39
res/dev-fs/apps/Finder/finder.css
Normal file
39
res/dev-fs/apps/Finder/finder.css
Normal 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;
|
||||||
|
}
|
317
res/dev-fs/apps/Finder/finder.js
Normal file
317
res/dev-fs/apps/Finder/finder.js
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
class Finder{
|
||||||
|
static AppId = "Finder"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string[]} args
|
||||||
|
*/
|
||||||
|
async NewWindow(args, runContext){
|
||||||
|
let newFinder = new FinderWindow()
|
||||||
|
await newFinder.Init(args, runContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
static async RenderProperites(path){
|
||||||
|
if (path == null || path ==""){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
path: path
|
||||||
|
})
|
||||||
|
const response = await fetch(`/app/${Finder.AppId}/renderProps?` + params)
|
||||||
|
if (response.status != 200){
|
||||||
|
WebDesktopEnvironment.Alert("Error in properties render") //TODO
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
let newWindow = WebDesktopEnvironment.CreateNewWindow(Finder.AppId, 350, 500 )
|
||||||
|
newWindow.innerHTML = html
|
||||||
|
newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) {
|
||||||
|
WebDesktopEnvironment.CloseWindow(newWindow)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FinderWindow{
|
||||||
|
curPath = ""
|
||||||
|
fileView = undefined
|
||||||
|
windowElem = undefined
|
||||||
|
|
||||||
|
async Init(args, appContext){
|
||||||
|
if (args[1] == "--desktop"){
|
||||||
|
let desktopNode = document.body.querySelector(`#${args[2]}`)
|
||||||
|
if (desktopNode == null){
|
||||||
|
WebDesktopEnvironment.Alert("Desktop node not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
path: args[0]
|
||||||
|
})
|
||||||
|
const response = await fetch(`/app/${Finder.AppId}/renderDesktop?` + params,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(appContext)
|
||||||
|
})
|
||||||
|
if (response.status != 200){
|
||||||
|
console.log(response.status)
|
||||||
|
WebDesktopEnvironment.Alert("Error in render desktop") //TODO
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
desktopNode.innerHTML = html
|
||||||
|
|
||||||
|
this.fileView = new FileView(
|
||||||
|
desktopNode.querySelector(".FileTileView"), (event) =>{this.Click(event)},
|
||||||
|
(event) => { this.RightClick(event) },
|
||||||
|
(event, draggedElem) => { this.DropEvent(event, draggedElem)},
|
||||||
|
() => { this.ReRenderDir() }
|
||||||
|
)
|
||||||
|
this.RenderDir(args[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const params = new URLSearchParams({isMobile: WebDesktopEnvironment.isMobile})
|
||||||
|
const response = await fetch(`/app/${Finder.AppId}/render?` + params,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(appContext)
|
||||||
|
})
|
||||||
|
if (response.status != 200){
|
||||||
|
const error = await response.json()
|
||||||
|
WebDesktopEnvironment.Alert(error.message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
|
||||||
|
let newWindow = WebDesktopEnvironment.CreateNewWindow(Finder.AppId, 500, 350 )
|
||||||
|
newWindow.innerHTML = html
|
||||||
|
|
||||||
|
this.fileView = new FileView(
|
||||||
|
newWindow.querySelector(".FileTileView"),
|
||||||
|
(event) => { this.Click(event) },
|
||||||
|
(event) => { this.RightClick(event) },
|
||||||
|
(event, draggedElem) => { this.DropEvent(event, draggedElem)},
|
||||||
|
() => { this.ReRenderDir() }
|
||||||
|
)
|
||||||
|
|
||||||
|
newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) {
|
||||||
|
|
||||||
|
WebDesktopEnvironment.CloseWindow(newWindow)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
newWindow.querySelector("#RootButton").addEventListener('click', () =>{
|
||||||
|
this.RenderDir('/')
|
||||||
|
})
|
||||||
|
|
||||||
|
newWindow.querySelector("#HomeButton").addEventListener('click', () =>{
|
||||||
|
this.RenderDir('/home/user')
|
||||||
|
})
|
||||||
|
|
||||||
|
let scrollBar = new WdeScrollBar(newWindow.querySelector(".ScrollbarPlace"), newWindow.querySelector(".FileTileView"))
|
||||||
|
|
||||||
|
this.windowElem = newWindow
|
||||||
|
this.RenderDir(args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
*/
|
||||||
|
RenderDir(path){
|
||||||
|
this.curPath = path
|
||||||
|
this.fileView.OpenFolder(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
ReRenderDir(){
|
||||||
|
this.RenderDir(this.curPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DragEvent} event
|
||||||
|
* @param {HTMLElement} draggedElem
|
||||||
|
*/
|
||||||
|
async DropEvent(event){
|
||||||
|
// console.log(event.dataTransfer.getData("dropType"))
|
||||||
|
if (event.dataTransfer.getData("dropType") == "move"){
|
||||||
|
const sourcePath= event.dataTransfer.getData("filePath")
|
||||||
|
const targetPath = this.curPath + "/" + event.dataTransfer.getData("fileName")
|
||||||
|
const res = await WebFS.MoveFile(sourcePath, targetPath)
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
} else {
|
||||||
|
WebDesktopEnvironment.Alert("UWAGA TODO MOVE FILE ERROR") //TODO
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(event, this.curPath)
|
||||||
|
let files = event.dataTransfer.files
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
const file = files[i];
|
||||||
|
console.log("file:" + file.name)
|
||||||
|
|
||||||
|
const res = await WebFS.UploadFile(file, this.curPath)
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
parentPath: this.curPath,
|
||||||
|
})
|
||||||
|
const response = await fetch('/fs/upload/?' + params,
|
||||||
|
{
|
||||||
|
method: "POST", //TODO Change to PUT?
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
if (response.status != 200){
|
||||||
|
WebDesktopEnvironment.Alert("ERROR IN UPLOADING FILE")//TODO
|
||||||
|
} else {
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MouseEvent} event
|
||||||
|
*/
|
||||||
|
Click(event){
|
||||||
|
this.OpenFile(this.curPath, event.target.getAttribute("name"), event.target.getAttribute("filetype"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} filePath
|
||||||
|
*/
|
||||||
|
async OpenFile(parentPath, fileName, fileType){
|
||||||
|
// console.log(parentPath, fileName, fileType)
|
||||||
|
// const splittedPath = filePath.split("/")
|
||||||
|
// const fileName = splittedPath[splittedPath.length - 1]
|
||||||
|
const fileExtension = fileName.split(".")[fileName.split(".").length - 1] //FIXME
|
||||||
|
|
||||||
|
switch (true) {
|
||||||
|
case fileType == "objectlink":
|
||||||
|
WebDesktopEnvironment.Alert("Links not supported yet")
|
||||||
|
break
|
||||||
|
case fileType == "pathlink":
|
||||||
|
let res = await WebFS.ReadPathLink(`${parentPath}/${fileName}`)
|
||||||
|
console.log(res)
|
||||||
|
this.OpenFile(res.parentPath, res.name, res.filetype)
|
||||||
|
break
|
||||||
|
case fileExtension == "app":
|
||||||
|
WebDesktopEnvironment.Open(`${parentPath}/${fileName}`, [])
|
||||||
|
break
|
||||||
|
case fileExtension == "blog":
|
||||||
|
WebDesktopEnvironment.Open(`/Applications/BlogViewer.app`, [`${parentPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
case fileType == "directory":
|
||||||
|
WebDesktopEnvironment.Open(`/Applications/Finder.app`, [`${parentPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
case fileExtension == "blog":
|
||||||
|
WebDesktopEnvironment.Open("/Applications/BlogViewer.app", [`${parentPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
case fileExtension == "jpeg" | fileExtension == "png":
|
||||||
|
WebDesktopEnvironment.Open("img-viewer", [`${parentPath}/${fileName}`])
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WebDesktopEnvironment.Alert("Unsupported file type")
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MouseEvent} event
|
||||||
|
*/
|
||||||
|
RightClick(event){
|
||||||
|
this.CreateContextMenu(event.target, [event.clientY, event.clientX])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
* @param {string[]} pos
|
||||||
|
*/
|
||||||
|
async CreateContextMenu(target, pos){
|
||||||
|
let context = ""
|
||||||
|
const fileName = target.getAttribute("name") //TODO check for null
|
||||||
|
const fileType = target.getAttribute("fileType")
|
||||||
|
if (target.classList.contains("FileTileView"))
|
||||||
|
{
|
||||||
|
context = "FileTileView"
|
||||||
|
} else {
|
||||||
|
context = fileType
|
||||||
|
}
|
||||||
|
let path = ""
|
||||||
|
if (fileName === null){
|
||||||
|
path = this.curPath
|
||||||
|
} else {
|
||||||
|
path = `${this.curPath}/${fileName}`
|
||||||
|
}
|
||||||
|
const params = new URLSearchParams({context: context, path: path})
|
||||||
|
const response = await fetch(`/app/${Finder.AppId}/contextMenu?` + params)
|
||||||
|
if (response.status != 200){
|
||||||
|
WebDesktopEnvironment.Alert("ERROR in Context menu TODO"); //TODO
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
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.top = pos[0] + "px";
|
||||||
|
menu.style.left = pos[1] + "px";
|
||||||
|
|
||||||
|
menu.innerHTML = html
|
||||||
|
// menu.children[0].firstElementChild.remove()
|
||||||
|
menu.children[0].lastElementChild.remove() //FIXME Can't ommit rendering of horLine in end of menu on backend
|
||||||
|
|
||||||
|
overlay.appendChild(menu)
|
||||||
|
document.body.appendChild(overlay)
|
||||||
|
|
||||||
|
overlay.addEventListener('click', async (event) => {
|
||||||
|
if (event.target.classList.contains("Row")){ //TODO add uuid id to rows to more accurate checks??
|
||||||
|
let res = false
|
||||||
|
switch (event.target.children[0].getAttribute("action")) {
|
||||||
|
case "createPathLink":
|
||||||
|
res = await WebFS.CreatePathLink(`${this.curPath}/${fileName}`, `${this.curPath}/Link to ${fileName}` )
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "createDir":
|
||||||
|
res = await WebFS.CreateDirectory(`${this.curPath}`)
|
||||||
|
console.log(res)
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "deleteFile":
|
||||||
|
res = await WebFS.DeleteFile(`${this.curPath}/${fileName}`)
|
||||||
|
console.log(res)
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "getInfo":
|
||||||
|
Finder.RenderProperites(path)
|
||||||
|
break
|
||||||
|
case "openAsDir":
|
||||||
|
WebDesktopEnvironment.Open(`/Applications/${Finder.AppId}.app`,[`${this.curPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
overlay.remove()
|
||||||
|
})
|
||||||
|
overlay.addEventListener('contextmenu', (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
overlay.remove()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
305
res/dev-fs/apps/FinderAdmin/FinderAdmin.js
Normal file
305
res/dev-fs/apps/FinderAdmin/FinderAdmin.js
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
class FinderAdmin{
|
||||||
|
static AppId = "FinderAdmin"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string[]} args
|
||||||
|
*/
|
||||||
|
async NewWindow(args, runContext){
|
||||||
|
let newFinder = new FinderWindow()
|
||||||
|
await newFinder.Init(args, runContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
static async RenderProperites(path){
|
||||||
|
if (path == null || path ==""){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
path: path
|
||||||
|
})
|
||||||
|
const response = await fetch(`/app/Finder/renderProps?` + params)
|
||||||
|
if (response.status != 200){
|
||||||
|
WebDesktopEnvironment.Alert("Error in properties render") //TODO
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
let newWindow = WebDesktopEnvironment.CreateNewWindow(FinderAdmin.AppId, 350, 500 )
|
||||||
|
newWindow.innerHTML = html
|
||||||
|
newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) {
|
||||||
|
WebDesktopEnvironment.CloseWindow(newWindow)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FinderWindow{
|
||||||
|
curPath = ""
|
||||||
|
fileView = undefined
|
||||||
|
windowElem = undefined
|
||||||
|
addressBar = undefined
|
||||||
|
|
||||||
|
async Init(args, runContext){
|
||||||
|
if (args[1] === "-desktop"){
|
||||||
|
//todo pass div id, not div in args[]
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
isMobile: WebDesktopEnvironment.isMobile,
|
||||||
|
path: args[0]
|
||||||
|
})
|
||||||
|
const response = await fetch(`/app/Finder/renderDesktop?` + params)
|
||||||
|
if (response.status != 200){
|
||||||
|
WebDesktopEnvironment.Alert("Error in render desktop") //TODO
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
args[2].innerHTML = html
|
||||||
|
|
||||||
|
this.fileView = new FileView(
|
||||||
|
args[2].querySelector(".FileTileView"), (event) =>{this.Click(event)},
|
||||||
|
(event) => { this.RightClick(event) },
|
||||||
|
(event, draggedElem) => { this.DropEvent(event, draggedElem)},
|
||||||
|
() => { this.ReRenderDir() }
|
||||||
|
)
|
||||||
|
this.RenderDir(args[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const params = new URLSearchParams({isMobile: WebDesktopEnvironment.isMobile})
|
||||||
|
const response = await fetch(`/app/Finder/render?` + params,{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(runContext)
|
||||||
|
})
|
||||||
|
if (response.status != 200){
|
||||||
|
const error = await response.json()
|
||||||
|
WebDesktopEnvironment.Alert(error.message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
|
||||||
|
let newWindow = WebDesktopEnvironment.CreateNewWindow(FinderAdmin.AppId, 500, 350 )
|
||||||
|
newWindow.innerHTML = html
|
||||||
|
|
||||||
|
this.fileView = new FileView(
|
||||||
|
newWindow.querySelector(".FileTileView"),
|
||||||
|
(event) => { this.Click(event) },
|
||||||
|
(event) => { this.RightClick(event) },
|
||||||
|
(event, draggedElem) => { this.DropEvent(event, draggedElem)},
|
||||||
|
() => { this.ReRenderDir() }
|
||||||
|
)
|
||||||
|
|
||||||
|
newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) {
|
||||||
|
WebDesktopEnvironment.CloseWindow(newWindow)
|
||||||
|
})
|
||||||
|
|
||||||
|
newWindow.querySelector("#RootButton").addEventListener('click', () =>{
|
||||||
|
this.RenderDir('/')
|
||||||
|
})
|
||||||
|
|
||||||
|
newWindow.querySelector("#HomeButton").addEventListener('click', () =>{
|
||||||
|
this.RenderDir('/home/user')
|
||||||
|
})
|
||||||
|
|
||||||
|
let scrollBar = new WdeScrollBar(newWindow.querySelector(".ScrollbarPlace"), newWindow.querySelector(".FileTileView"))
|
||||||
|
|
||||||
|
this.windowElem = newWindow
|
||||||
|
this.addressBar = newWindow.querySelector(".AddressBar")
|
||||||
|
this.RenderDir(args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
*/
|
||||||
|
RenderDir(path){
|
||||||
|
console.log(path)
|
||||||
|
this.curPath = path
|
||||||
|
this.addressBar.innerHTML = path
|
||||||
|
this.fileView.OpenFolder(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
ReRenderDir(){
|
||||||
|
this.RenderDir(this.curPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DragEvent} event
|
||||||
|
* @param {HTMLElement} draggedElem
|
||||||
|
*/
|
||||||
|
async DropEvent(event){
|
||||||
|
// console.log(event.dataTransfer.getData("dropType"))
|
||||||
|
if (event.dataTransfer.getData("dropType") == "move"){
|
||||||
|
const sourcePath= event.dataTransfer.getData("filePath")
|
||||||
|
const targetPath = this.curPath + "/" + event.dataTransfer.getData("fileName")
|
||||||
|
const res = await WebFS.MoveFile(sourcePath, targetPath)
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
} else {
|
||||||
|
WebDesktopEnvironment.Alert("UWAGA TODO MOVE FILE ERROR") //TODO
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(event, this.curPath)
|
||||||
|
let files = event.dataTransfer.files
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
const file = files[i];
|
||||||
|
console.log("file:" + file.name)
|
||||||
|
|
||||||
|
const res = await WebFS.UploadFile(file, this.curPath)
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
parentPath: this.curPath,
|
||||||
|
})
|
||||||
|
const response = await fetch('/fs/upload/?' + params,
|
||||||
|
{
|
||||||
|
method: "POST", //TODO Change to PUT?
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
if (response.status != 200){
|
||||||
|
WebDesktopEnvironment.Alert("ERROR IN UPLOADING FILE")//TODO
|
||||||
|
} else {
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MouseEvent} event
|
||||||
|
*/
|
||||||
|
Click(event){
|
||||||
|
this.OpenFile(this.curPath, event.target.getAttribute("name"), event.target.getAttribute("filetype"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} filePath
|
||||||
|
*/
|
||||||
|
async OpenFile(parentPath, fileName, fileType){
|
||||||
|
// console.log(parentPath, fileName, fileType)
|
||||||
|
// const splittedPath = filePath.split("/")
|
||||||
|
// const fileName = splittedPath[splittedPath.length - 1]
|
||||||
|
const fileExtension = fileName.split(".")[fileName.split(".").length - 1] //FIXME
|
||||||
|
|
||||||
|
switch (true) {
|
||||||
|
case fileType == "objectlink":
|
||||||
|
WebDesktopEnvironment.Alert("Links not supported yet")
|
||||||
|
break
|
||||||
|
case fileType == "pathlink":
|
||||||
|
let res = await WebFS.ReadPathLink(`${parentPath}/${fileName}`)
|
||||||
|
console.log(res)
|
||||||
|
this.OpenFile(res.parentPath, res.name, res.filetype)
|
||||||
|
break
|
||||||
|
case fileExtension == "app":
|
||||||
|
WebDesktopEnvironment.Open(`${parentPath}/${fileName}`, [])
|
||||||
|
break
|
||||||
|
case fileType == "directory":
|
||||||
|
WebDesktopEnvironment.Open(`/Applications/Finder.app`, [`${parentPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
case fileExtension == "blog":
|
||||||
|
WebDesktopEnvironment.Open("/Applications/BlogViewer.app", [`${parentPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
case fileExtension == "jpeg" | fileExtension == "png":
|
||||||
|
WebDesktopEnvironment.Open("img-viewer", [`${parentPath}/${fileName}`])
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WebDesktopEnvironment.Alert("Unsupported file type")
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {MouseEvent} event
|
||||||
|
*/
|
||||||
|
RightClick(event){
|
||||||
|
this.CreateContextMenu(event.target, [event.clientY, event.clientX])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
* @param {string[]} pos
|
||||||
|
*/
|
||||||
|
async CreateContextMenu(target, pos){
|
||||||
|
let context = ""
|
||||||
|
const fileName = target.getAttribute("name") //TODO check for null
|
||||||
|
const fileType = target.getAttribute("fileType")
|
||||||
|
if (target.classList.contains("FileTileView"))
|
||||||
|
{
|
||||||
|
context = "FileTileView"
|
||||||
|
} else {
|
||||||
|
context = fileType
|
||||||
|
}
|
||||||
|
let path = ""
|
||||||
|
if (fileName === null){
|
||||||
|
path = this.curPath
|
||||||
|
} else {
|
||||||
|
path = `${this.curPath}/${fileName}`
|
||||||
|
}
|
||||||
|
const params = new URLSearchParams({context: context, path: path})
|
||||||
|
const response = await fetch(`/app/Finder/contextMenu?` + params)
|
||||||
|
if (response.status != 200){
|
||||||
|
WebDesktopEnvironment.Alert("ERROR in Context menu TODO"); //TODO
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
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.top = pos[0] + "px";
|
||||||
|
menu.style.left = pos[1] + "px";
|
||||||
|
|
||||||
|
menu.innerHTML = html
|
||||||
|
menu.children[0].firstElementChild.remove()
|
||||||
|
menu.children[0].lastElementChild.remove() //FIXME Can't ommit rendering of horLine in end of menu on backend
|
||||||
|
|
||||||
|
overlay.appendChild(menu)
|
||||||
|
document.body.appendChild(overlay)
|
||||||
|
|
||||||
|
overlay.addEventListener('click', async (event) => {
|
||||||
|
if (event.target.classList.contains("Row")){ //TODO add uuid id to rows to more accurate checks??
|
||||||
|
let res = false
|
||||||
|
switch (event.target.children[0].getAttribute("action")) {
|
||||||
|
case "createPathLink":
|
||||||
|
res = await WebFS.CreatePathLink(`${this.curPath}/${fileName}`, `${this.curPath}/Link to ${fileName}` )
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "createDir":
|
||||||
|
res = await WebFS.CreateDirectory(`${this.curPath}`)
|
||||||
|
console.log(res)
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "deleteFile":
|
||||||
|
res = await WebFS.DeleteFile(`${this.curPath}/${fileName}`)
|
||||||
|
console.log(res)
|
||||||
|
if (res){
|
||||||
|
this.ReRenderDir()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "getInfo":
|
||||||
|
Finder.RenderProperites(path)
|
||||||
|
break
|
||||||
|
case "openAsDir":
|
||||||
|
WebDesktopEnvironment.Open(`/Applications/Finder.app`,[`${this.curPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
overlay.remove()
|
||||||
|
})
|
||||||
|
overlay.addEventListener('contextmenu', (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
overlay.remove()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
53
res/dev-fs/apps/FinderAdmin/finder-admin.css
Normal file
53
res/dev-fs/apps/FinderAdmin/finder-admin.css
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
.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;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content:left;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 0px;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ToolBar .AddressBar{
|
||||||
|
width:100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
18
res/dev-fs/apps/ImgViewer/img-viewer.css
Normal file
18
res/dev-fs/apps/ImgViewer/img-viewer.css
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
.Img-Viewer-Picture-Container{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.Img-Viewer-Picture{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
/* background-image: url("./test-image.jpg");
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center center; */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.Img-Viewer-Picture-Toolbar{
|
||||||
|
width: 100%;
|
||||||
|
height: 35px;
|
||||||
|
}
|
27
res/dev-fs/apps/ImgViewer/img-viewer.js
Normal file
27
res/dev-fs/apps/ImgViewer/img-viewer.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
class ImgViewer{
|
||||||
|
appId = "img-viewer"
|
||||||
|
/**
|
||||||
|
* @param {string[]} args
|
||||||
|
*/
|
||||||
|
NewWindow(args){
|
||||||
|
fetch(`${window.location.origin}/application/${this.appId}/render?`+ new URLSearchParams({
|
||||||
|
isMobile: WebDesktopEnvironment.isMobile,
|
||||||
|
path: args[0]
|
||||||
|
}))
|
||||||
|
.then((response) => response.text())
|
||||||
|
.then((html) => {
|
||||||
|
let newWindow = WebDesktopEnvironment.CreateNewWindow(this.appId, 450,400 )
|
||||||
|
newWindow.innerHTML = html
|
||||||
|
|
||||||
|
if (!WebDesktopEnvironment.isMobile){
|
||||||
|
newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) {
|
||||||
|
WebDesktopEnvironment.CloseWindow(newWindow)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
WebDesktopEnvironment.Alert(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
BIN
res/dev-fs/apps/ImgViewer/test-image.jpg
(Stored with Git LFS)
Normal file
BIN
res/dev-fs/apps/ImgViewer/test-image.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
0
res/dev-fs/libs/fs.js
Normal file
0
res/dev-fs/libs/fs.js
Normal file
73
res/dev-fs/wde/base.css
Normal file
73
res/dev-fs/wde/base.css
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
@font-face{
|
||||||
|
font-family: "Virtue";
|
||||||
|
src:url("/res/dev-fs/fonts/virtue.ttf");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @font-face{
|
||||||
|
font-family: "Virtue";
|
||||||
|
src:url("/res/dev-fs/fonts/virtue.ttf")
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* @media screen and (max-device-width: 2048px) and (max-device-height: 2048px) {
|
||||||
|
html {
|
||||||
|
zoom: 3
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
.NoClick {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.Click {
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
*{
|
||||||
|
font-family: Verdana, Geneva, sans-serif;
|
||||||
|
font-size: 11px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight:initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar { /* WebKit */
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body{
|
||||||
|
zoom: var(--zoom);
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0px;
|
||||||
|
|
||||||
|
/* font: normal 14px Summer Pixel 22, "res/SummerPixel22Regular.ttf"; */
|
||||||
|
-webkit-touch-callout: none; /* iOS Safari */
|
||||||
|
-webkit-user-select: none; /* Safari */
|
||||||
|
-khtml-user-select: none; /* Konqueror HTML */
|
||||||
|
-moz-user-select: none; /* Old versions of Firefox */
|
||||||
|
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||||
|
user-select: none; /* Non-prefixed version, currently
|
||||||
|
supported by Chrome, Edge, Opera and Firefox */
|
||||||
|
touch-action: manipulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
#applications{
|
||||||
|
position: static;
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#windows-layer {
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
/* position: fixed; */
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
|
||||||
|
#desktop-layer{
|
||||||
|
position: fixed;
|
||||||
|
/* margin: 0px; */
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #9999CC;
|
||||||
|
}
|
60
res/dev-fs/wde/basic-widgets.css
Normal file
60
res/dev-fs/wde/basic-widgets.css
Normal 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;
|
||||||
|
}
|
54
res/dev-fs/wde/decorat.js
Normal file
54
res/dev-fs/wde/decorat.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
class WindowsCompositor{
|
||||||
|
static windowsLayer
|
||||||
|
|
||||||
|
constructor(){
|
||||||
|
this.windowLayer = document.body.querySelector('#windows-layer')
|
||||||
|
WindowsCompositor.windowsLayer = document.body.querySelector('#windows-layer')
|
||||||
|
if (!WebDesktopEnvironment.isMobile) {
|
||||||
|
let startDrag = function(event) {
|
||||||
|
let window = event.target.closest('.WindowFrame')
|
||||||
|
WindowsCompositor.bringWindowToFront(window)
|
||||||
|
if (event.target.classList.contains("DragArea")){
|
||||||
|
let xPosInit = event.offsetX
|
||||||
|
let yPosInit = event.offsetY
|
||||||
|
let dragWindow = function(event){
|
||||||
|
window.style.left = `${event.clientX - xPosInit}px`
|
||||||
|
window.style.top = `${event.clientY - yPosInit}px`
|
||||||
|
}
|
||||||
|
let stopDrag = function(){
|
||||||
|
removeEventListener('mousemove', dragWindow)
|
||||||
|
removeEventListener('mouseup', stopDrag)
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListener('mousemove', dragWindow)
|
||||||
|
addEventListener('mouseup', stopDrag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WindowsCompositor.windowsLayer.addEventListener('mousedown', startDrag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} window
|
||||||
|
*/
|
||||||
|
static bringWindowToFront(window){ //FIXME
|
||||||
|
let previousWindow = WindowsCompositor.windowsLayer.lastChild
|
||||||
|
if (window == null || window == undefined){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (window != previousWindow){
|
||||||
|
WindowsCompositor.windowsLayer.insertBefore(window, previousWindow.nextSibling)
|
||||||
|
previousWindow.classList.remove("Focused")
|
||||||
|
window.classList.add("Focused")
|
||||||
|
} else {
|
||||||
|
window.classList.add("Focused")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ChangeURL(appWindow){
|
||||||
|
let appId = appWindow.getAttribute('appid')
|
||||||
|
window.history.replaceState(null, "", `/${appId}/`);
|
||||||
|
}
|
||||||
|
}
|
0
res/dev-fs/wde/desktop.js
Normal file
0
res/dev-fs/wde/desktop.js
Normal file
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user