Compare commits
3 Commits
edf011fccd
...
c5c277f516
Author | SHA1 | Date | |
---|---|---|---|
c5c277f516 | |||
d018477fe3 | |||
d61fa2bd4b |
6
.gitignore
vendored
6
.gitignore
vendored
@ -24,4 +24,8 @@ go.work
|
|||||||
/__debug_bin
|
/__debug_bin
|
||||||
/.env
|
/.env
|
||||||
|
|
||||||
front/node_modules/**
|
|
||||||
|
front/node_modules
|
||||||
|
.parcel-cache
|
||||||
|
**/node_modules/
|
||||||
|
front/node_modules/*
|
@ -57,13 +57,13 @@ func (p *AboutMeApp) PublicRoutes(route *gin.RouterGroup) {
|
|||||||
|
|
||||||
func (p *AboutMeApp) PrivateRoutes(router *gin.RouterGroup) {
|
func (p *AboutMeApp) PrivateRoutes(router *gin.RouterGroup) {
|
||||||
p.PublicRoutes(router)
|
p.PublicRoutes(router)
|
||||||
// router.GET("writeMock", func(ctx *gin.Context) {
|
router.GET("writeMock", func(ctx *gin.Context) {
|
||||||
// err := p.WriteMock()
|
err := p.WriteMock()
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// ctx.Status(http.StatusInternalServerError)
|
ctx.Status(http.StatusInternalServerError)
|
||||||
// }
|
}
|
||||||
// ctx.Status(http.StatusOK)
|
ctx.Status(http.StatusOK)
|
||||||
// })
|
})
|
||||||
|
|
||||||
router.GET("getMock", func(ctx *gin.Context) {
|
router.GET("getMock", func(ctx *gin.Context) {
|
||||||
ctx.JSON(http.StatusOK, PropertiesFileData{
|
ctx.JSON(http.StatusOK, PropertiesFileData{
|
||||||
@ -153,72 +153,22 @@ func (p *AboutMeApp) GetAppID() string {
|
|||||||
return p.appID
|
return p.appID
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (p *AboutMeApp) WriteMock() error {
|
func (p *AboutMeApp) WriteMock() error {
|
||||||
// fileHeader := webfilesystem.FileHeader{
|
fileHeader := webfilesystem.FileHeader{
|
||||||
// MongoId: primitive.NewObjectID(),
|
MongoId: primitive.NewObjectID(),
|
||||||
// Name: "aboutme.props",
|
Name: "aboutme.props",
|
||||||
// Type: "personal-properties",
|
Type: "personal-properties",
|
||||||
// Icon: "",
|
Icon: "",
|
||||||
// }
|
}
|
||||||
// fileData := PropertiesFileData{
|
fileData := PropertiesFileData{
|
||||||
// Header: HeaderIsland{
|
Header: HeaderIsland{
|
||||||
// Name: "Test Name",
|
Name: "Test Name",
|
||||||
// IconPath: "test icon path",
|
IconPath: "test icon path",
|
||||||
// Info1: "Info1",
|
},
|
||||||
// Info2: "Info2",
|
}
|
||||||
// },
|
_, _, err := p.fs.Write("/Applications/AboutMe.app/aboutme.props", &fileHeader, fileData)
|
||||||
// Props: []PropIsland{
|
return err
|
||||||
// {
|
}
|
||||||
// Header: "Test Prop Header",
|
|
||||||
// Props: []PropElement{
|
|
||||||
// {
|
|
||||||
// Key: "Test key",
|
|
||||||
// KeyComments: []string{"Test key comment 1", "Test key comment 1"},
|
|
||||||
// Values: []Value{
|
|
||||||
// {
|
|
||||||
// Blocks: []ValueBlock{
|
|
||||||
// {
|
|
||||||
// Type: "string",
|
|
||||||
// Data: []string{"aappo"},
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// Type: "link",
|
|
||||||
// Data: []string{"https://ya.ru", "Azazaza"},
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// Header: "Test Prop Header 2",
|
|
||||||
// Props: []PropElement{
|
|
||||||
// {
|
|
||||||
// Key: "Test key",
|
|
||||||
// KeyComments: []string{"Test key comment 1", "Test key comment 1"},
|
|
||||||
// Values: []Value{
|
|
||||||
// {
|
|
||||||
// Blocks: []ValueBlock{
|
|
||||||
// {
|
|
||||||
// Type: "string",
|
|
||||||
// Data: []string{"aappo"},
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// Type: "link",
|
|
||||||
// Data: []string{"https://ya.ru", "Azazaza"},
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
// _, _, err := p.fs.Write("/Applications/AboutMe.app/aboutme.props", &fileHeader, fileData)
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (p *AboutMeApp) Read(filePath string) (*PropertiesFileData, error) {
|
func (p *AboutMeApp) Read(filePath string) (*PropertiesFileData, error) {
|
||||||
propData := PropertiesFileData{}
|
propData := PropertiesFileData{}
|
||||||
@ -236,7 +186,12 @@ func (p *AboutMeApp) Edit(filePath string, blogData PropertiesFileData) error {
|
|||||||
propsPath := path.Join(filePath, "aboutme.props")
|
propsPath := path.Join(filePath, "aboutme.props")
|
||||||
fileHeader, err := p.fs.Read(propsPath, nil)
|
fileHeader, err := p.fs.Read(propsPath, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
if err.Error() == "file not found" { //FIXME
|
||||||
|
p.WriteMock()
|
||||||
|
p.Edit(filePath, blogData)
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if fileHeader.Type != "personal-properties" {
|
if fileHeader.Type != "personal-properties" {
|
||||||
return errors.New("wrong file type")
|
return errors.New("wrong file type")
|
||||||
|
@ -44,6 +44,7 @@ func (a *SunboardApp) PrivateRoutes(router *gin.RouterGroup) {
|
|||||||
Icon: "",
|
Icon: "",
|
||||||
Lable: app.GetAppID(),
|
Lable: app.GetAppID(),
|
||||||
AppId: app.GetAppID(),
|
AppId: app.GetAppID(),
|
||||||
|
Path: "/Applications/" + app.GetAppID() + ".app", //FIXME
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ctx.HTML(http.StatusOK, "sunboard/sunboard.html", gin.H{
|
ctx.HTML(http.StatusOK, "sunboard/sunboard.html", gin.H{
|
||||||
@ -57,4 +58,5 @@ type appIcon struct {
|
|||||||
Type string
|
Type string
|
||||||
Icon string
|
Icon string
|
||||||
Lable string
|
Lable string
|
||||||
|
Path string
|
||||||
}
|
}
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"plugins": ["@babel/syntax-dynamic-import"],
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"@babel/preset-env",
|
|
||||||
{
|
|
||||||
"modules": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
# 🚀 Welcome to your new awesome project!
|
|
||||||
|
|
||||||
This project has been created using **webpack-cli**, you can now run
|
|
||||||
|
|
||||||
```
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```
|
|
||||||
yarn build
|
|
||||||
```
|
|
||||||
|
|
||||||
to bundle your application
|
|
149
front/dist/apps/about-me/about-me.css
vendored
Normal file
149
front/dist/apps/about-me/about-me.css
vendored
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
.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;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
order: 0;
|
||||||
|
align-self: stretch;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
margin-right: 20px;
|
||||||
|
padding: 0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ShortBio .Name {
|
||||||
|
letter-spacing: .35px;
|
||||||
|
font-family: Virtue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PropertiesList .Links {
|
||||||
|
align-items: left;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 4px;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
top: 27px;
|
||||||
|
right: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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 {
|
||||||
|
letter-spacing: .35px;
|
||||||
|
background-color: #ddd;
|
||||||
|
max-width: 100%;
|
||||||
|
font-family: Virtue;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
top: -9px;
|
||||||
|
left: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Focused .Island .Title {
|
||||||
|
background-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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 {
|
||||||
|
letter-spacing: .35px;
|
||||||
|
text-align: end;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 34%;
|
||||||
|
font-family: Virtue;
|
||||||
|
font-size: 11px;
|
||||||
|
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":"AAwBA;;;;;;;;;;AAYA;;;;;AAKA;;;;;;;;;;;AAkBA;;;;;;;;;;;;AAoBA;;;;;;AAMA;;;;;;;;;;;AAkBA;;;;;AAMA;;;;;;;;;;;;;AAgBA;;;;;AAMA;;;;;;;;AAeA;;;;;;;;;;;AAYA;;;;AAIA;;;;;;;;;AAWA;;;;;;;;;;AAUA;;;;;;;;;;;AAaA;;;;;;;;AAUA","sources":["src/apps/about-me/about-me.less"],"sourcesContent":["/* TODO Move this to body? */\n/*.ScrollContent {\n width: 100%;\n height: 100%;\n overflow: scroll;\n overflow-x: hidden;\n /* Firefox */\n /* scrollbar-width: none; */\n /* Internet Explorer 10+ */\n /* -ms-overflow-style: none; */\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/* WebKit */\n/* .ScrollContent::-webkit-scrollbar { \n width: 0;\n height: 0;\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 /* 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: 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 .Name{\n font-family: \"Virtue\";\n /* FIXME */\n letter-spacing: 0.35px; \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 /* Auto layout */\n display: flex;\n flex-direction: row;\n align-items: left;\n padding: 0px;\n gap:4px;\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 font-family: \"Virtue\";\n /* FIXME */\n letter-spacing: 0.35px; \n position:relative;\n display: inline-block;\n max-width: 100%;\n background-color: #DDDDDD;\n left: 12px;\n top: -9px;\n}\n\n.Focused .Island .Title{\n background-color: #CCCCCC;\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 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}"],"names":[],"version":3,"file":"about-me.css.map","sourceRoot":"/__parcel_source_root/"}
|
34
front/dist/apps/finder/finder.css
vendored
Normal file
34
front/dist/apps/finder/finder.css
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
.FinderContent {
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FinderContent .ToolBar {
|
||||||
|
background-color: #eee;
|
||||||
|
border-bottom: 1px solid #555;
|
||||||
|
width: 100%;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Focused .FinderContent .ToolBar {
|
||||||
|
background-color: #ddd;
|
||||||
|
border-bottom: 1px solid #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FinderContent .FinderFileView {
|
||||||
|
background-color: #fff;
|
||||||
|
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":"AAAA;;;;;;;;;;AAYA;;;;;;;AAOA;;;;;AAOA","sources":["src/apps/finder/finder.less"],"sourcesContent":[".FinderContent {\n width: 100%;\n height: 100%;\n\n /* Auto layout */\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: flex-start;\n padding: 0px;\n}\n\n.FinderContent .ToolBar{\n width: 100%;\n height: 20px;\n border-bottom: 1px solid #555555;\n background-color: #EEEEEE;\n}\n\n.Focused .FinderContent .ToolBar{\n border-bottom: 1px solid #000000;\n background-color: #DDDDDD;\n}\n\n\n\n.FinderContent .FinderFileView{\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}"],"names":[],"version":3,"file":"finder.css.map","sourceRoot":"/__parcel_source_root/"}
|
329
front/dist/desktop.css
vendored
Normal file
329
front/dist/desktop.css
vendored
Normal file
@ -0,0 +1,329 @@
|
|||||||
|
.WdePrimitives.AdjectiveElement {
|
||||||
|
border: 1px solid #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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 {
|
||||||
|
image-rendering: optimizespeed;
|
||||||
|
image-rendering: -moz-crisp-edges;
|
||||||
|
image-rendering: -o-crisp-edges;
|
||||||
|
image-rendering: -webkit-optimize-contrast;
|
||||||
|
image-rendering: pixelated;
|
||||||
|
image-rendering: optimize-contrast;
|
||||||
|
-ms-interpolation-mode: nearest-neighbor;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrame {
|
||||||
|
background: #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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrame.Focused {
|
||||||
|
background-color: #ccc;
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrameShadow {
|
||||||
|
box-shadow: 2px 2px #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrameShadow.Focused {
|
||||||
|
box-shadow: 2px 2px #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ConvexElement.Focused {
|
||||||
|
box-shadow: 1px 1px #00000040, inset -1px -1px #00000045, inset 1px 1px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.AdjectiveElement {
|
||||||
|
border: 1px solid #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Focused .AdjectiveElement {
|
||||||
|
border: 1px solid #000;
|
||||||
|
box-shadow: -1px -1px #00000040, 1px 1px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.AdjectiveHorizontalLine {
|
||||||
|
border-top: 1px solid #00000040;
|
||||||
|
border-bottom: 1px solid #fff;
|
||||||
|
width: 100%;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.AdjectiveHorizontalLine:last-child {
|
||||||
|
visibility: hidden;
|
||||||
|
height: 0%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrame .TitleBar {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrame .TitleBar .Lable {
|
||||||
|
color: #777;
|
||||||
|
pointer-events: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
letter-spacing: .35px;
|
||||||
|
font-family: Virtue;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrame.Focused .TitleBar .Lable {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrame .TitleBar .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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrame.Focused .TitleBar .Button {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WindowFrame .TitleBar .Button:active {
|
||||||
|
background-color: #0006;
|
||||||
|
box-shadow: .5px .5px 0 .5px #fff, -.5px -.5px 0 .5px #00000040;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Focused .VisualDragArea {
|
||||||
|
pointer-events: none;
|
||||||
|
filter: drop-shadow(1px 1px #777);
|
||||||
|
background: linear-gradient(#0000 0%, #fff 0% 50%, #0000 50%) 0 0 / 2px 2px;
|
||||||
|
width: 100%;
|
||||||
|
height: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MobileContentBorder {
|
||||||
|
background-color: #ddd;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MobileApplicationWindow {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 4px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MobileWindowFrameBottomBar {
|
||||||
|
flex: none;
|
||||||
|
order: 0;
|
||||||
|
align-self: stretch;
|
||||||
|
width: 100%;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MobileWindowFrameBottomBarButton {
|
||||||
|
background: linear-gradient(135deg, #999 18.18%, #fff 81.82%);
|
||||||
|
border: 1px solid #222;
|
||||||
|
flex: none;
|
||||||
|
order: 0;
|
||||||
|
width: auto;
|
||||||
|
min-width: 11px;
|
||||||
|
height: 15px;
|
||||||
|
padding: 0 4px;
|
||||||
|
position: absolute;
|
||||||
|
right: 4px;
|
||||||
|
box-shadow: .5px .5px 0 .5px #fff, -.5px -.5px 0 .5px #00000040, inset 1px 1px #ffffff80, inset -1px -1px #00000045;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MobileWindowFrameBottomBar .MobileLable {
|
||||||
|
pointer-events: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
letter-spacing: .35px;
|
||||||
|
font-family: Virtue;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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 {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
zoom: var(--zoom);
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
touch-action: manipulation;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
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;;;;ACAA;;;;;AASA;;;;AAKA;;;;;;;;;;;;;AAqBA;;;;;AAKA;;;;;;;;;;;AAkBA;;;;;;;;;;;;;AAeA;;;;AAIA;;;;AAIA;;;;;;ACjFA;;;;;;;;;;;;;;AAwBA;;;;;AAKA;;;;AAKA;;;;AAIA;;;;AAMA;;;;AAIA;;;;;AAQA;;;;;;;AAOA;;;;;AAMA;;;;;;;;;;;;;;AAmBA;;;;;;;;;;AAYA;;;;AAKA;;;;;;;;;;;;;;AAoBA;;;;AAIA;;;;;AAOA;;;;;;;;AASA;;;;;;;;;;;;AAsBA;;;;;;;;;;;;AAcA;;;;;;;;AAkBA;;;;;;;;;;;;;;AAqBA;;;;;;;;;AC5NA;;;;;;AAUA;;;;;;;;AAUA;;;;;;;;;AAgBA;;;;;AAYA;;;;;AAKA;;;;;;;AJ/BA;;;;AAGA;;;;AAGA;;;;;;;AAOA;;;;;AAKA;;;;;;;;;;;;;AAkBA;;;;;;;AAOA;;;;;;AAOA","sources":["src/desktop.less","src/wde/primitives.less","src/wde/widgets/file-view/file-view.less","src/wde/legacy-ui.less","src/wde/widgets/basic-widgets.less"],"sourcesContent":["@import \"./wde/primitives.less\";\n@import \"./wde/widgets/file-view/file-view.less\";\n@import \"./wde/legacy-ui.less\";\n@import \"./wde/widgets/basic-widgets.less\";\n@import \"./theme.less\";\n\n// @font-face{\n// font-family: \"Virtue\";\n// src:url(\"/res/dev-fs/fonts/virtue.ttf\");\n// }\n\n/* @font-face{\n font-family: \"Virtue\";\n src:url(\"/res/dev-fs/fonts/virtue.ttf\")\n} */\n\n/* @media screen and (max-device-width: 2048px) and (max-device-height: 2048px) {\n html {\n zoom: 3\n }\n } */\n\n.NoClick {\n pointer-events: none;\n}\n.Click {\n pointer-events: all;\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 zoom: var(--zoom);\n position: absolute;\n width: 100%;\n height: 100%;\n margin: 0px;\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],"names":[],"version":3,"file":"desktop.css.map","sourceRoot":"/__parcel_source_root/"}
|
89
front/dist/mobile.css
vendored
Normal file
89
front/dist/mobile.css
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
.WdePrimitives.AdjectiveElement {
|
||||||
|
border: 1px solid #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mobile-sunboard {
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#icons {
|
||||||
|
background-color: #99c;
|
||||||
|
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: 103px 18px;
|
||||||
|
padding: 64px 32px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-icon {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-icon .icon {
|
||||||
|
background-color: beige;
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
zoom: 2;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
touch-action: manipulation;
|
||||||
|
background-image: linear-gradient(45deg, silver 25%, #0000 25%), linear-gradient(45deg, #0000 75%, silver 75%), linear-gradient(45deg, #0000 75%, silver 75%), linear-gradient(45deg, silver 25%, #777 25%);
|
||||||
|
background-position: 0 0, 0 0, -5px -5px, 5px 5px;
|
||||||
|
background-size: 10px 10px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mobile-app-views {
|
||||||
|
background: #99c;
|
||||||
|
border: 1px solid #000;
|
||||||
|
border-radius: 15px;
|
||||||
|
position: absolute;
|
||||||
|
inset: 16px 16px 128px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#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%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*# 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;;;;ACGA;;;;;;;;;AAWA;;;;;;AAaA;;;;;;;;;;;AAYA;;;;;;;;;;AAYA;;;;;;AFjDA;;;;;;;;;;;;;;;;AAmCA;;;;;;;;;AAYA;;;;;;;;;;;;AAiBA","sources":["src/mobile.less","src/wde/primitives.less","src/wde/sunboard/sunboard-mobile.less"],"sourcesContent":["@import \"./wde/sunboard/sunboard-mobile.less\";\n\nbody{\n zoom: 2;\n position: absolute;\n width: 100%;\n height: 100%;\n margin: 0px;\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 // /* 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: 128px;\n \n border-radius: 15px;\n border: 1px solid #000;\n background: #99C;\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}",null,null],"names":[],"version":3,"file":"mobile.css.map","sourceRoot":"/__parcel_source_root/"}
|
@ -1,12 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<title>Webpack App</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Hello world!</h1>
|
|
||||||
<h2>Tip: Check your console</h2>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
15830
front/package-lock.json
generated
15830
front/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,31 +1,6 @@
|
|||||||
{
|
{
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.2",
|
"@parcel/transformer-less": "^2.9.3",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"parcel": "^2.9.3"
|
||||||
"@webpack-cli/generators": "^3.0.7",
|
|
||||||
"babel-loader": "^9.1.0",
|
|
||||||
"css-loader": "^6.7.2",
|
|
||||||
"less": "^4.1.3",
|
|
||||||
"less-loader": "^11.1.0",
|
|
||||||
"mini-css-extract-plugin": "^2.7.6",
|
|
||||||
"style-loader": "^3.3.1",
|
|
||||||
"webpack": "^5.88.2",
|
|
||||||
"webpack-cli": "^5.1.4",
|
|
||||||
"webpack-dev-server": "^4.11.1"
|
|
||||||
},
|
|
||||||
"type": "module",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "My webpack project",
|
|
||||||
"name": "my-webpack-project",
|
|
||||||
"scripts": {
|
|
||||||
"build": "webpack --mode=production --node-env=production",
|
|
||||||
"build:dev": "webpack --mode=development",
|
|
||||||
"build:prod": "webpack --mode=production --node-env=production",
|
|
||||||
"watch": "webpack --watch",
|
|
||||||
"watch:prod": "webpack --watch --mode=production --node-env=production",
|
|
||||||
"serve": "webpack serve"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"request": "^2.79.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
220
front/src/apps/about-me/about-me.less
Normal file
220
front/src/apps/about-me/about-me.less
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
/* TODO Move this to body? */
|
||||||
|
/*.ScrollContent {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
|
/* Firefox */
|
||||||
|
/* scrollbar-width: none; */
|
||||||
|
/* Internet Explorer 10+ */
|
||||||
|
/* -ms-overflow-style: none; */
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
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; */
|
||||||
|
|
||||||
|
/* Inside auto layout */
|
||||||
|
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 .Name{
|
||||||
|
font-family: "Virtue";
|
||||||
|
/* FIXME */
|
||||||
|
letter-spacing: 0.35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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%;
|
||||||
|
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 {
|
||||||
|
font-family: "Virtue";
|
||||||
|
/* FIXME */
|
||||||
|
letter-spacing: 0.35px;
|
||||||
|
position:relative;
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 100%;
|
||||||
|
background-color: #DDDDDD;
|
||||||
|
left: 12px;
|
||||||
|
top: -9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Focused .Island .Title{
|
||||||
|
background-color: #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
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%; */
|
||||||
|
|
||||||
|
}
|
@ -1,28 +1,40 @@
|
|||||||
// import WebDesktopEnvironment from "../../wde/wde-desktop"
|
import AbstractWebDesktopEnvironment from "../../wde/wde.js"
|
||||||
|
import Finder from "./finder.js"
|
||||||
|
|
||||||
// import Finder from "./finder"
|
|
||||||
|
|
||||||
// import WebDesktopEnvironment from "../../wde/wde-desktop"
|
|
||||||
|
|
||||||
export default class FinderWindow{
|
export default class FinderWindow{
|
||||||
#appId = "Finder" //FIXME
|
#appId = "Finder" //FIXME
|
||||||
curPath = ""
|
curPath = ""
|
||||||
fileView = undefined
|
fileView = undefined
|
||||||
windowElem = undefined
|
windowElem = undefined
|
||||||
/** @type {WebDesktopEnvironment} */
|
/** @type {Finder} */
|
||||||
#wde
|
|
||||||
#finder
|
#finder
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* @type {AbstractWebDesktopEnvironment}
|
||||||
|
*/
|
||||||
|
#wde
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {Finder}
|
||||||
|
* @param {AbstractWebDesktopEnvironment} wde
|
||||||
|
*/
|
||||||
|
constructor(finder, wde){
|
||||||
|
this.#finder = finder
|
||||||
|
this.#wde = wde
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @param {Finder} finder
|
* @param {Finder} finder
|
||||||
* @param {*} args
|
* @param {*} args
|
||||||
* @param {import("../../wde/wde-desktop").runContext} runContext
|
* @param {import("../../wde/wde.js").runContext} runContext
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async Init(finder, args, runContext){
|
async Init(finder, args, runContext){
|
||||||
|
console.log(args)
|
||||||
this.#finder = finder
|
this.#finder = finder
|
||||||
this.#wde = runContext.WDE
|
|
||||||
if (runContext.isMobile){
|
if (runContext.isMobile){
|
||||||
|
console.log("Mobile Finder!")
|
||||||
this.CreateMobileView(args, runContext)
|
this.CreateMobileView(args, runContext)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -43,18 +55,20 @@ export default class FinderWindow{
|
|||||||
})
|
})
|
||||||
if (response.status != 200){
|
if (response.status != 200){
|
||||||
console.log(response.status)
|
console.log(response.status)
|
||||||
this.#wde.Alert("Error in render desktop") //TODO
|
// this.#wde.Alert("Error in render desktop") //TODO
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const html = await response.text()
|
const html = await response.text()
|
||||||
desktopNode.innerHTML = html
|
desktopNode.innerHTML = html
|
||||||
|
|
||||||
this.fileView = new runContext.WDE.FileView(
|
// console.log(this.#wde)
|
||||||
|
|
||||||
|
this.fileView = new this.#wde.FileView(
|
||||||
desktopNode.querySelector(".FileTileView"), (event) =>{this.Click(event)},
|
desktopNode.querySelector(".FileTileView"), (event) =>{this.Click(event)},
|
||||||
(event) => { this.RightClick(event) },
|
(event) => { this.RightClick(event) },
|
||||||
(event, draggedElem) => { this.DropEvent(event, draggedElem)},
|
(event, draggedElem) => { this.DropEvent(event, draggedElem)},
|
||||||
() => { this.ReRenderDir() }
|
() => { this.ReRenderDir() },
|
||||||
)
|
this.#wde)
|
||||||
this.RenderDir(args[0])
|
this.RenderDir(args[0])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -76,13 +90,13 @@ export default class FinderWindow{
|
|||||||
|
|
||||||
// console.log(this.#wde)
|
// console.log(this.#wde)
|
||||||
|
|
||||||
this.fileView = new runContext.WDE.FileView(
|
this.fileView = new this.#wde.FileView(
|
||||||
newWindow.querySelector(".FileTileView"),
|
newWindow.querySelector(".FileTileView"),
|
||||||
(event) => { this.Click(event) },
|
(event) => { this.Click(event) },
|
||||||
(event) => { this.RightClick(event) },
|
(event) => { this.RightClick(event) },
|
||||||
(event, draggedElem) => { this.DropEvent(event, draggedElem)},
|
(event, draggedElem) => { this.DropEvent(event, draggedElem)},
|
||||||
() => { this.ReRenderDir() }
|
() => { this.ReRenderDir() },
|
||||||
)
|
this.#wde)
|
||||||
|
|
||||||
newWindow.querySelector("#closeWindowButton").addEventListener('click', () => {
|
newWindow.querySelector("#closeWindowButton").addEventListener('click', () => {
|
||||||
this.#wde.Decorat.CloseWindow(newWindow)
|
this.#wde.Decorat.CloseWindow(newWindow)
|
||||||
@ -108,7 +122,7 @@ export default class FinderWindow{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {*} args
|
* @param {*} args
|
||||||
* @param {import("../../wde/wde-desktop").runContext} runContext
|
* @param {import("../../wde/wde-desktop.js").runContext} runContext
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async CreateMobileView(args, runContext){
|
async CreateMobileView(args, runContext){
|
||||||
@ -126,7 +140,7 @@ export default class FinderWindow{
|
|||||||
}
|
}
|
||||||
const html = await response.text()
|
const html = await response.text()
|
||||||
console.log(this.#wde)
|
console.log(this.#wde)
|
||||||
let newView = this.#wde.Decorat.CreateNewView(this.#appId,)
|
let newView = this.#wde.Decorat.CreateNewView(this.#appId)
|
||||||
newView.innerHTML = html
|
newView.innerHTML = html
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -1,37 +1,38 @@
|
|||||||
// require("./finder.less")
|
// require("./finder.less")
|
||||||
|
|
||||||
import WDEApplication from "../../wde/application.js"
|
import WDEApplication from "../../wde/application.js"
|
||||||
import WebDesktopEnvironment from "../../wde/wde-desktop.js"
|
import AbstractWebDesktopEnvironment from "../../wde/wde.js"
|
||||||
import FinderWindow from "./finder-window.js"
|
import FinderWindow from "./finder-window.js"
|
||||||
|
|
||||||
export default class Finder extends WDEApplication{
|
export default class Finder extends WDEApplication{
|
||||||
|
/** @deprecated */
|
||||||
static AppId = "Finder"
|
static AppId = "Finder"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {WebDesktopEnvironment} wde
|
* @param {AbstractWebDesktopEnvironment} wde
|
||||||
*/
|
*/
|
||||||
constructor(wde){
|
constructor(wde){
|
||||||
/** @type {WDEApplication} */
|
super(wde, "Finder")
|
||||||
super(wde)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string[]} args
|
* @param {string[]} args
|
||||||
* @param {import("../../wde/wde-desktop.js").runContext} runContext
|
* @param {import("../../wde/wde.js").runContext} runContext
|
||||||
*/
|
*/
|
||||||
async NewWindow(args, runContext){
|
async NewWindow(args, runContext){
|
||||||
let newFinder = new FinderWindow()
|
|
||||||
await newFinder.Init(this, args, runContext)
|
|
||||||
|
|
||||||
|
let newFinder = new FinderWindow(this, super.WDE())
|
||||||
|
await newFinder.Init(this, args, runContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string[]} args
|
* @param {string[]} args
|
||||||
* @param {import("../../wde/wde-desktop.js").runContext} runContext
|
* @param {import("../../wde/wde.js").runContext} runContext
|
||||||
*/
|
*/
|
||||||
async NewView(args, runContext){
|
async NewView(args, runContext){
|
||||||
let newFinderView = new FinderWindow(this, args, runContext)
|
// console.log(super.WDE())
|
||||||
|
let newFinderView = new FinderWindow(this, super.WDE())
|
||||||
await newFinderView.Init(this, args, runContext)
|
await newFinderView.Init(this, args, runContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +41,6 @@ export default class Finder extends WDEApplication{
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
async RenderProperites(path){
|
async RenderProperites(path){
|
||||||
|
|
||||||
// return
|
// return
|
||||||
if (path == null || path ==""){
|
if (path == null || path ==""){
|
||||||
return
|
return
|
||||||
@ -48,6 +48,7 @@ export default class Finder extends WDEApplication{
|
|||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
path: path
|
path: path
|
||||||
})
|
})
|
||||||
|
|
||||||
const response = await fetch(`/app/${Finder.AppId}/renderProps?` + params)
|
const response = await fetch(`/app/${Finder.AppId}/renderProps?` + params)
|
||||||
if (response.status != 200){
|
if (response.status != 200){
|
||||||
// WebDesktopEnvironment.Alert("Error in properties render") //TODO
|
// WebDesktopEnvironment.Alert("Error in properties render") //TODO
|
||||||
@ -55,7 +56,7 @@ export default class Finder extends WDEApplication{
|
|||||||
}
|
}
|
||||||
const html = await response.text()
|
const html = await response.text()
|
||||||
|
|
||||||
let newWindow = super.getWde().Decorat.CreateNewWindow(Finder.AppId, 350, 500 )
|
let newWindow = super.WDE().Decorat.CreateNewWindow(Finder.AppId, 350, 500 )
|
||||||
newWindow.innerHTML = html
|
newWindow.innerHTML = html
|
||||||
newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) {
|
newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) {
|
||||||
// WebDesktopEnvironment.CloseWindow(newWindow)
|
// WebDesktopEnvironment.CloseWindow(newWindow)
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
import WebDesktopEnvironment from "./wde/wde-desktop.js";
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
let wde = new WebDesktopEnvironment()
|
|
||||||
}, false);
|
|
@ -1,5 +0,0 @@
|
|||||||
import MobileWebDesktopEnvironment from "./wde/wde-mobile";
|
|
||||||
require("./mobile.less")
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
let wde = new MobileWebDesktopEnvironment()
|
|
||||||
}, false);
|
|
@ -1,7 +1,7 @@
|
|||||||
@import "./wde/sunboard/sunboard-mobile.less";
|
@import "./wde/sunboard/sunboard-mobile.less";
|
||||||
|
|
||||||
body{
|
body{
|
||||||
zoom: var(--zoom);
|
zoom: 2;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -17,30 +17,51 @@ body{
|
|||||||
supported by Chrome, Edge, Opera and Firefox */
|
supported by Chrome, Edge, Opera and Firefox */
|
||||||
touch-action: manipulation;
|
touch-action: manipulation;
|
||||||
|
|
||||||
/* Auto layout */
|
// /* Auto layout */
|
||||||
display: flex;
|
// display: flex;
|
||||||
flex-direction: column;
|
// flex-direction: column;
|
||||||
align-items: flex-start;
|
// align-items: flex-start;
|
||||||
justify-content: 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{
|
#mobile-app-views{
|
||||||
width: 100%;
|
position: absolute;
|
||||||
height: 100%;
|
// background-color: aqua;
|
||||||
// background-color: @col-ceil;
|
inset: 16px;
|
||||||
|
bottom: 128px;
|
||||||
|
|
||||||
|
border-radius: 15px;
|
||||||
|
border: 1px solid #000;
|
||||||
|
background: #99C;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
#controls-bar{
|
#controls-bar{
|
||||||
&:extend(.WdePrimitives.AdjectiveElement);
|
position: absolute;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 150px;
|
height: 100px;
|
||||||
background-color: @col-argent;
|
// background-color: @col-argent;
|
||||||
|
bottom: 0px;
|
||||||
|
|
||||||
/* Auto layout */
|
/* Auto layout */
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
// padding: 10px;
|
||||||
align-items: flex-start;
|
justify-content: center;
|
||||||
justify-content: flex-start;
|
align-items: center;
|
||||||
|
gap: 53px;
|
||||||
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-app-view{
|
.mobile-app-view{
|
||||||
|
339
front/src/src/apps copy/finder/finder-window.js
Normal file
339
front/src/src/apps copy/finder/finder-window.js
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
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
|
||||||
|
/** @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){
|
||||||
|
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.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
|
||||||
|
|
||||||
|
// console.log(this.#wde)
|
||||||
|
|
||||||
|
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() }
|
||||||
|
)
|
||||||
|
|
||||||
|
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(".ScrollbarPlace"), 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.#wde.Alert(error.message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
console.log(this.#wde)
|
||||||
|
let newView = this.#wde.Decorat.CreateNewView(this.#appId,)
|
||||||
|
newView.innerHTML = html
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @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 {
|
||||||
|
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 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} 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":
|
||||||
|
this.#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.#wde.Open(`${parentPath}/${fileName}`, [])
|
||||||
|
break
|
||||||
|
case fileExtension == "blog":
|
||||||
|
this.#wde.Open(`/Applications/BlogViewer.app`, [`${parentPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
case fileType == "directory":
|
||||||
|
this.#wde.Open(`/Applications/Finder.app`, [`${parentPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
case fileExtension == "blog":
|
||||||
|
this.#wde.Open("/Applications/BlogViewer.app", [`${parentPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
case fileExtension == "jpeg" | fileExtension == "png":
|
||||||
|
this.#wde.Open("img-viewer", [`${parentPath}/${fileName}`])
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.#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 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":
|
||||||
|
this.#wde.Open(`/Applications/${this.#appId}.app`,[`${this.curPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
overlay.remove()
|
||||||
|
})
|
||||||
|
overlay.addEventListener('contextmenu', (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
overlay.remove()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
64
front/src/src/apps copy/finder/finder.js
Normal file
64
front/src/src/apps copy/finder/finder.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// 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){
|
||||||
|
// console.log(super.WDE())
|
||||||
|
let newFinderView = new FinderWindow(this, super.WDE())
|
||||||
|
await newFinderView.Init(this, args, runContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
async RenderProperites(path){
|
||||||
|
// return
|
||||||
|
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 = super.WDE().Decorat.CreateNewWindow(Finder.AppId, 350, 500 )
|
||||||
|
newWindow.innerHTML = html
|
||||||
|
newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) {
|
||||||
|
// WebDesktopEnvironment.CloseWindow(newWindow)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
39
front/src/src/apps copy/finder/finder.less
Normal file
39
front/src/src/apps copy/finder/finder.less
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;
|
||||||
|
}
|
79
front/src/src/apps/desktop.less
Normal file
79
front/src/src/apps/desktop.less
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
@import "./wde/primitives.less";
|
||||||
|
@import "./wde/widgets/file-view/file-view.less";
|
||||||
|
@import "./wde/legacy-ui.less";
|
||||||
|
@import "./wde/widgets/basic-widgets.less";
|
||||||
|
@import "./theme.less";
|
||||||
|
|
||||||
|
// @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: @col-ceil;
|
||||||
|
}
|
339
front/src/src/apps/finder/finder-window.js
Normal file
339
front/src/src/apps/finder/finder-window.js
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
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
|
||||||
|
/** @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){
|
||||||
|
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.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
|
||||||
|
|
||||||
|
// console.log(this.#wde)
|
||||||
|
|
||||||
|
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() }
|
||||||
|
)
|
||||||
|
|
||||||
|
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(".ScrollbarPlace"), newWindow.querySelector(".FileTileView"))
|
||||||
|
|
||||||
|
this.windowElem = newWindow
|
||||||
|
this.RenderDir(args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateDesktopWindow(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} args
|
||||||
|
* @param {import("../../wde/wde-desktop").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.#wde.Alert(error.message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const html = await response.text()
|
||||||
|
console.log(this.#wde)
|
||||||
|
let newView = this.#wde.Decorat.CreateNewView(this.#appId,)
|
||||||
|
newView.innerHTML = html
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @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 {
|
||||||
|
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 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} 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":
|
||||||
|
this.#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.#wde.Open(`${parentPath}/${fileName}`, [])
|
||||||
|
break
|
||||||
|
case fileExtension == "blog":
|
||||||
|
this.#wde.Open(`/Applications/BlogViewer.app`, [`${parentPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
case fileType == "directory":
|
||||||
|
this.#wde.Open(`/Applications/Finder.app`, [`${parentPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
case fileExtension == "blog":
|
||||||
|
this.#wde.Open("/Applications/BlogViewer.app", [`${parentPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
case fileExtension == "jpeg" | fileExtension == "png":
|
||||||
|
this.#wde.Open("img-viewer", [`${parentPath}/${fileName}`])
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.#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 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":
|
||||||
|
this.#wde.Open(`/Applications/${this.#appId}.app`,[`${this.curPath}/${fileName}`])
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
overlay.remove()
|
||||||
|
})
|
||||||
|
overlay.addEventListener('contextmenu', (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
overlay.remove()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
64
front/src/src/apps/finder/finder.js
Normal file
64
front/src/src/apps/finder/finder.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// 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){
|
||||||
|
// console.log(super.WDE())
|
||||||
|
let newFinderView = new FinderWindow(this, super.WDE())
|
||||||
|
await newFinderView.Init(this, args, runContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
async RenderProperites(path){
|
||||||
|
// return
|
||||||
|
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 = super.WDE().Decorat.CreateNewWindow(Finder.AppId, 350, 500 )
|
||||||
|
newWindow.innerHTML = html
|
||||||
|
newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) {
|
||||||
|
// WebDesktopEnvironment.CloseWindow(newWindow)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
39
front/src/src/apps/finder/finder.less
Normal file
39
front/src/src/apps/finder/finder.less
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;
|
||||||
|
}
|
54
front/src/src/apps/mobile.less
Normal file
54
front/src/src/apps/mobile.less
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
@import "./wde/sunboard/sunboard-mobile.less";
|
||||||
|
|
||||||
|
body{
|
||||||
|
zoom: 2;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mobile-app-views{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
// padding: 64px;
|
||||||
|
// border-radius: 50px;
|
||||||
|
// overflow:hidden
|
||||||
|
// background-color: @col-ceil;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls-bar{
|
||||||
|
&:extend(.WdePrimitives.AdjectiveElement);
|
||||||
|
width: 100%;
|
||||||
|
height: 150px;
|
||||||
|
background-color: @col-argent;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-app-view{
|
||||||
|
// background-color: burlywood;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
// position: absolute;
|
||||||
|
}
|
2
front/src/src/apps/theme.less
Normal file
2
front/src/src/apps/theme.less
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
@col-ceil: #9999CC;
|
||||||
|
@col-argent: #C0C0C0;
|
32
front/src/src/apps/wde/application.js
Normal file
32
front/src/src/apps/wde/application.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import AbstractWebDesktopEnvironment from "./wde.js"
|
||||||
|
|
||||||
|
export default class WDEApplication{
|
||||||
|
/** @type {AbstractWebDesktopEnvironment} */
|
||||||
|
#wde
|
||||||
|
/** @type {string} */
|
||||||
|
AppId
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {AbstractWebDesktopEnvironment} wde
|
||||||
|
*/
|
||||||
|
constructor(wde, AppId){
|
||||||
|
this.#wde = wde
|
||||||
|
// console.log(wde)
|
||||||
|
this.AppId = AppId
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {AbstractWebDesktopEnvironment} */
|
||||||
|
WDE(){
|
||||||
|
return this.#wde
|
||||||
|
}
|
||||||
|
|
||||||
|
async NewWindow(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {Element} */
|
||||||
|
async NewView(){
|
||||||
|
return this.#wde.Decorat.CreateNewView(this.AppId)
|
||||||
|
}
|
||||||
|
}
|
104
front/src/src/apps/wde/decorat/desktop-decorat.js
Normal file
104
front/src/src/apps/wde/decorat/desktop-decorat.js
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
export default class DesktopDecorat{
|
||||||
|
/** @type {Element} */
|
||||||
|
#windowsLayer
|
||||||
|
|
||||||
|
constructor(){
|
||||||
|
this.windowLayer = document.body.querySelector('#windows-layer')
|
||||||
|
// this.#windowsLayer = document.body.querySelector('#windows-layer')
|
||||||
|
this.#windowsLayer = document.body.querySelector('#windows-layer')
|
||||||
|
let startDrag = (event) => {
|
||||||
|
let window = event.target.closest('.WindowFrame')
|
||||||
|
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("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;
|
||||||
|
}
|
||||||
|
}
|
27
front/src/src/apps/wde/decorat/mobile-decorat.js
Normal file
27
front/src/src/apps/wde/decorat/mobile-decorat.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
export default class MobileDecorat {
|
||||||
|
/** @type {Element} */
|
||||||
|
#applicationsNode
|
||||||
|
constructor(){
|
||||||
|
this.#applicationsNode = document.body.querySelector("#mobile-app-views") //TODO validate
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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)
|
||||||
|
return newView
|
||||||
|
}
|
||||||
|
Open(){
|
||||||
|
|
||||||
|
}
|
||||||
|
BackAction(){
|
||||||
|
// console.log(this.#applicationsNode.childNodes.length)
|
||||||
|
if (this.#applicationsNode.childNodes.length <= 1) return
|
||||||
|
this.#applicationsNode.lastChild.remove()
|
||||||
|
}
|
||||||
|
}
|
232
front/src/src/apps/wde/legacy-ui.less
Normal file
232
front/src/src/apps/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;
|
||||||
|
|
||||||
|
}
|
3
front/src/src/apps/wde/primitives.less
Normal file
3
front/src/src/apps/wde/primitives.less
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.WdePrimitives.AdjectiveElement {
|
||||||
|
border: 1px solid #555555;
|
||||||
|
}
|
54
front/src/src/apps/wde/scrollbar/scrollbar.js
Normal file
54
front/src/src/apps/wde/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(".ScrollBarScrollElement") //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/src/apps/wde/scrollbar/wde-scrollbar.css
Normal file
110
front/src/src/apps/wde/scrollbar/wde-scrollbar.css
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ScrollbarPlace{
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
border-left: 1px solid #555555;
|
||||||
|
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 .ScrollbarPlace{
|
||||||
|
border-left: 1px solid #000000;
|
||||||
|
background-color: #AAAAAA;
|
||||||
|
box-shadow: inset -1px 0px 0px rgba(255, 255, 255, 0.29),
|
||||||
|
inset -2px 0px 0px rgba(255, 255, 255, 0.19),
|
||||||
|
inset 1px 1px 0px rgba(0, 0, 0, 0.14),
|
||||||
|
inset 2px 2px 0px rgba(0, 0, 0, 0.19);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ScrollBarScrollElement{
|
||||||
|
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 .ScrollBarScrollElement{
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ScrollBarScrollElementDrag{
|
||||||
|
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;
|
||||||
|
}
|
50
front/src/src/apps/wde/sunboard/sunboard-mobile.js
Normal file
50
front/src/src/apps/wde/sunboard/sunboard-mobile.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
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 = await 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 appId = element.getAttribute('appId')
|
||||||
|
element.addEventListener('click', () => {
|
||||||
|
// console.log(appId)
|
||||||
|
// this.#wde.Decorat.CreateNewView(appId)
|
||||||
|
this.#wde.Open("/Applications/Finder.app", [""], "")
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async createFileView(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
61
front/src/src/apps/wde/sunboard/sunboard-mobile.less
Normal file
61
front/src/src/apps/wde/sunboard/sunboard-mobile.less
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
@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 32px;
|
||||||
|
align-items: flex-start;
|
||||||
|
align-content: flex-start;
|
||||||
|
gap: 103px 18px;
|
||||||
|
flex: 1 0 0;
|
||||||
|
align-self: stretch;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-icon{
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
padding: 4px 8px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-icon .icon{
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
background-color: beige;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-icon .lable{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
173
front/src/src/apps/wde/wde-desktop.js
Normal file
173
front/src/src/apps/wde/wde-desktop.js
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
import DesktopDecorat from "./decorat/desktop-decorat.js";
|
||||||
|
import WDEScrollBar from "./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
|
||||||
|
|
||||||
|
constructor(){
|
||||||
|
super()
|
||||||
|
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(){
|
||||||
|
let autoStart = document.body.querySelector("wde-autostart")
|
||||||
|
if (autoStart == null){
|
||||||
|
WebDesktopEnvironment.Alert("Error in loading DE")
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} appManifest
|
||||||
|
* @param {function} onload callback after script loading
|
||||||
|
*/
|
||||||
|
static async load2(appManifest, onload){
|
||||||
|
// import(window.location.origin + appManifest.js[0]).then((app) => {
|
||||||
|
// console.log(window.location.origin + appManifest.js[0] == 'http://localhost:8080/res/dev-fs/wde/dist/finder.js')
|
||||||
|
// let kek = 'http://localhost:8080/res/dev-fs/wde/dist/finder.js'
|
||||||
|
import('http://localhost:8080/res/dev-fs/dist/finder.js').then((app) => {
|
||||||
|
let newApp = new app.default()
|
||||||
|
// if newApp //TODO Validate
|
||||||
|
WebDesktopEnvironment.Applications[appManifest.appId] = newApp;
|
||||||
|
onload()
|
||||||
|
})
|
||||||
|
|
||||||
|
return //TODO return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {Object | undefined} //FIXME
|
||||||
|
*/
|
||||||
|
static async fetchApp(path){
|
||||||
|
// console.log("path: " + path )
|
||||||
|
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)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
//TODO Validate manifest
|
||||||
|
const appManifest = response.json()
|
||||||
|
return appManifest
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} html
|
||||||
|
*/
|
||||||
|
static SetBasicWindow(html){
|
||||||
|
this.basicWindow = html
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
static GetBasicWindow(){
|
||||||
|
return this.basicWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} alertText
|
||||||
|
*/
|
||||||
|
static Alert(alertText){
|
||||||
|
WebDesktopEnvironment.CreateAlertWindow(alertText)
|
||||||
|
console.log(alertText)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} alertText
|
||||||
|
*/
|
||||||
|
static 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
52
front/src/src/apps/wde/wde-mobile.js
Normal file
52
front/src/src/apps/wde/wde-mobile.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
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()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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) =>{
|
||||||
|
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()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
94
front/src/src/apps/wde/wde.js
Normal file
94
front/src/src/apps/wde/wde.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import WDEApplication from "./application.js"
|
||||||
|
|
||||||
|
export default class AbstractWebDesktopEnvironment{
|
||||||
|
/** @type {Object<string, WDEApplication>} */
|
||||||
|
_applications = {}
|
||||||
|
/** @type {AbstractWebDesktopEnvironment} */
|
||||||
|
#wde
|
||||||
|
|
||||||
|
/** @type {AbstractWebDesktopEnvironment} */
|
||||||
|
_SetWDE(wde){
|
||||||
|
this.#wde = wde
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {Object | undefined} //FIXME
|
||||||
|
*/
|
||||||
|
async _FetchAppManifest(path){
|
||||||
|
// console.log("path: " + path )
|
||||||
|
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
|
||||||
|
await import(/* webpackMode: "eager" */ `${window.location.origin}/res/dev-fs/dist/finder.js`).then((app) => {newApp = app})
|
||||||
|
// let newApp
|
||||||
|
// switch (appManifest.appId) { //FIXME Can't dynamicly load es6 modules withou static pathes
|
||||||
|
// case 'Finder':
|
||||||
|
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
let newAppClass = new newApp.default(this.#wde)
|
||||||
|
this._applications[appManifest.appId] = newAppClass
|
||||||
|
onload()
|
||||||
|
return //TODO return result
|
||||||
|
}
|
||||||
|
|
||||||
|
_GetApp(appId){
|
||||||
|
// console.log(appId)
|
||||||
|
return this._applications[appId]
|
||||||
|
}
|
||||||
|
|
||||||
|
_fetchComp(res) {
|
||||||
|
import(`${window.location.origin}${res}`).then(() => {
|
||||||
|
console.log("Loaded")
|
||||||
|
}, (err)=>{
|
||||||
|
console.log("Error", err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} runContext
|
||||||
|
* @property {boolean} isMobile
|
||||||
|
* @property {string} appPath
|
||||||
|
* @property {string} runPath //TODO
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** //TODO
|
||||||
|
* @typedef {Object} appManifest
|
||||||
|
*/
|
60
front/src/src/apps/wde/widgets/basic-widgets.less
Normal file
60
front/src/src/apps/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;
|
||||||
|
}
|
134
front/src/src/apps/wde/widgets/file-view/file-view.js
Normal file
134
front/src/src/apps/wde/widgets/file-view/file-view.js
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export default class WDEFileView{
|
||||||
|
path = ""
|
||||||
|
parentElem = undefined
|
||||||
|
selected = []
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} fileViewElem
|
||||||
|
* @param {Function} doubleClickCallback
|
||||||
|
* @param {Function} rightClickCallback
|
||||||
|
* @param {Function} updateFileViewCallback
|
||||||
|
*/
|
||||||
|
constructor(fileViewElem, doubleClickCallback, rightClickCallback, fileUploadCallback, updateFileViewCallback){
|
||||||
|
//TODO check all params
|
||||||
|
this.parentElem = fileViewElem
|
||||||
|
|
||||||
|
fileViewElem.addEventListener('click', (event) => {
|
||||||
|
if (event.target.classList[0] == 'FileTileView')
|
||||||
|
{
|
||||||
|
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
|
||||||
|
WebDesktopEnvironment.Alert("TODO")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let html = await response.text()
|
||||||
|
this.parentElem.innerHTML = html
|
||||||
|
}
|
||||||
|
}
|
86
front/src/src/apps/wde/widgets/file-view/file-view.less
Normal file
86
front/src/src/apps/wde/widgets/file-view/file-view.less
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
.FileTileView{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
131
front/src/src/apps/web-fs/web-fs.js
Normal file
131
front/src/src/apps/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
|
||||||
|
}
|
||||||
|
}
|
79
front/src/src/desktop.less
Normal file
79
front/src/src/desktop.less
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
@import "./wde/primitives.less";
|
||||||
|
@import "./wde/widgets/file-view/file-view.less";
|
||||||
|
@import "./wde/legacy-ui.less";
|
||||||
|
@import "./wde/widgets/basic-widgets.less";
|
||||||
|
@import "./theme.less";
|
||||||
|
|
||||||
|
// @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: @col-ceil;
|
||||||
|
}
|
3
front/src/src/init.mjs
Normal file
3
front/src/src/init.mjs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default class Kek{
|
||||||
|
|
||||||
|
}
|
54
front/src/src/mobile.less
Normal file
54
front/src/src/mobile.less
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
@import "./wde/sunboard/sunboard-mobile.less";
|
||||||
|
|
||||||
|
body{
|
||||||
|
zoom: 2;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mobile-app-views{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
// padding: 64px;
|
||||||
|
// border-radius: 50px;
|
||||||
|
// overflow:hidden
|
||||||
|
// background-color: @col-ceil;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls-bar{
|
||||||
|
&:extend(.WdePrimitives.AdjectiveElement);
|
||||||
|
width: 100%;
|
||||||
|
height: 150px;
|
||||||
|
background-color: @col-argent;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-app-view{
|
||||||
|
// background-color: burlywood;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
// position: absolute;
|
||||||
|
}
|
2
front/src/src/theme.less
Normal file
2
front/src/src/theme.less
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
@col-ceil: #9999CC;
|
||||||
|
@col-argent: #C0C0C0;
|
32
front/src/src/wde/application.js
Normal file
32
front/src/src/wde/application.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import AbstractWebDesktopEnvironment from "./wde.js"
|
||||||
|
|
||||||
|
export default class WDEApplication{
|
||||||
|
/** @type {AbstractWebDesktopEnvironment} */
|
||||||
|
#wde
|
||||||
|
/** @type {string} */
|
||||||
|
AppId
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {AbstractWebDesktopEnvironment} wde
|
||||||
|
*/
|
||||||
|
constructor(wde, AppId){
|
||||||
|
this.#wde = wde
|
||||||
|
// console.log(wde)
|
||||||
|
this.AppId = AppId
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {AbstractWebDesktopEnvironment} */
|
||||||
|
WDE(){
|
||||||
|
return this.#wde
|
||||||
|
}
|
||||||
|
|
||||||
|
async NewWindow(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {Element} */
|
||||||
|
async NewView(){
|
||||||
|
return this.#wde.Decorat.CreateNewView(this.AppId)
|
||||||
|
}
|
||||||
|
}
|
104
front/src/src/wde/decorat/desktop-decorat.js
Normal file
104
front/src/src/wde/decorat/desktop-decorat.js
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
export default class DesktopDecorat{
|
||||||
|
/** @type {Element} */
|
||||||
|
#windowsLayer
|
||||||
|
|
||||||
|
constructor(){
|
||||||
|
this.windowLayer = document.body.querySelector('#windows-layer')
|
||||||
|
// this.#windowsLayer = document.body.querySelector('#windows-layer')
|
||||||
|
this.#windowsLayer = document.body.querySelector('#windows-layer')
|
||||||
|
let startDrag = (event) => {
|
||||||
|
let window = event.target.closest('.WindowFrame')
|
||||||
|
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("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;
|
||||||
|
}
|
||||||
|
}
|
27
front/src/src/wde/decorat/mobile-decorat.js
Normal file
27
front/src/src/wde/decorat/mobile-decorat.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
export default class MobileDecorat {
|
||||||
|
/** @type {Element} */
|
||||||
|
#applicationsNode
|
||||||
|
constructor(){
|
||||||
|
this.#applicationsNode = document.body.querySelector("#mobile-app-views") //TODO validate
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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)
|
||||||
|
return newView
|
||||||
|
}
|
||||||
|
Open(){
|
||||||
|
|
||||||
|
}
|
||||||
|
BackAction(){
|
||||||
|
// console.log(this.#applicationsNode.childNodes.length)
|
||||||
|
if (this.#applicationsNode.childNodes.length <= 1) return
|
||||||
|
this.#applicationsNode.lastChild.remove()
|
||||||
|
}
|
||||||
|
}
|
232
front/src/src/wde/legacy-ui.less
Normal file
232
front/src/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;
|
||||||
|
|
||||||
|
}
|
3
front/src/src/wde/primitives.less
Normal file
3
front/src/src/wde/primitives.less
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.WdePrimitives.AdjectiveElement {
|
||||||
|
border: 1px solid #555555;
|
||||||
|
}
|
54
front/src/src/wde/scrollbar/scrollbar.js
Normal file
54
front/src/src/wde/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(".ScrollBarScrollElement") //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/src/wde/scrollbar/wde-scrollbar.css
Normal file
110
front/src/src/wde/scrollbar/wde-scrollbar.css
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ScrollbarPlace{
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
border-left: 1px solid #555555;
|
||||||
|
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 .ScrollbarPlace{
|
||||||
|
border-left: 1px solid #000000;
|
||||||
|
background-color: #AAAAAA;
|
||||||
|
box-shadow: inset -1px 0px 0px rgba(255, 255, 255, 0.29),
|
||||||
|
inset -2px 0px 0px rgba(255, 255, 255, 0.19),
|
||||||
|
inset 1px 1px 0px rgba(0, 0, 0, 0.14),
|
||||||
|
inset 2px 2px 0px rgba(0, 0, 0, 0.19);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ScrollBarScrollElement{
|
||||||
|
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 .ScrollBarScrollElement{
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ScrollBarScrollElementDrag{
|
||||||
|
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;
|
||||||
|
}
|
50
front/src/src/wde/sunboard/sunboard-mobile.js
Normal file
50
front/src/src/wde/sunboard/sunboard-mobile.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
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 = await 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 appId = element.getAttribute('appId')
|
||||||
|
element.addEventListener('click', () => {
|
||||||
|
// console.log(appId)
|
||||||
|
// this.#wde.Decorat.CreateNewView(appId)
|
||||||
|
this.#wde.Open("/Applications/Finder.app", [""], "")
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async createFileView(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
61
front/src/src/wde/sunboard/sunboard-mobile.less
Normal file
61
front/src/src/wde/sunboard/sunboard-mobile.less
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
@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 32px;
|
||||||
|
align-items: flex-start;
|
||||||
|
align-content: flex-start;
|
||||||
|
gap: 103px 18px;
|
||||||
|
flex: 1 0 0;
|
||||||
|
align-self: stretch;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-icon{
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
|
||||||
|
/* Auto layout */
|
||||||
|
display: flex;
|
||||||
|
padding: 4px 8px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-icon .icon{
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
background-color: beige;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-icon .lable{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
173
front/src/src/wde/wde-desktop.js
Normal file
173
front/src/src/wde/wde-desktop.js
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
import DesktopDecorat from "./decorat/desktop-decorat.js";
|
||||||
|
import WDEScrollBar from "./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
|
||||||
|
|
||||||
|
constructor(){
|
||||||
|
super()
|
||||||
|
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(){
|
||||||
|
let autoStart = document.body.querySelector("wde-autostart")
|
||||||
|
if (autoStart == null){
|
||||||
|
WebDesktopEnvironment.Alert("Error in loading DE")
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} appManifest
|
||||||
|
* @param {function} onload callback after script loading
|
||||||
|
*/
|
||||||
|
static async load2(appManifest, onload){
|
||||||
|
// import(window.location.origin + appManifest.js[0]).then((app) => {
|
||||||
|
// console.log(window.location.origin + appManifest.js[0] == 'http://localhost:8080/res/dev-fs/wde/dist/finder.js')
|
||||||
|
// let kek = 'http://localhost:8080/res/dev-fs/wde/dist/finder.js'
|
||||||
|
import('http://localhost:8080/res/dev-fs/dist/finder.js').then((app) => {
|
||||||
|
let newApp = new app.default()
|
||||||
|
// if newApp //TODO Validate
|
||||||
|
WebDesktopEnvironment.Applications[appManifest.appId] = newApp;
|
||||||
|
onload()
|
||||||
|
})
|
||||||
|
|
||||||
|
return //TODO return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {Object | undefined} //FIXME
|
||||||
|
*/
|
||||||
|
static async fetchApp(path){
|
||||||
|
// console.log("path: " + path )
|
||||||
|
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)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
//TODO Validate manifest
|
||||||
|
const appManifest = response.json()
|
||||||
|
return appManifest
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} html
|
||||||
|
*/
|
||||||
|
static SetBasicWindow(html){
|
||||||
|
this.basicWindow = html
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
static GetBasicWindow(){
|
||||||
|
return this.basicWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} alertText
|
||||||
|
*/
|
||||||
|
static Alert(alertText){
|
||||||
|
WebDesktopEnvironment.CreateAlertWindow(alertText)
|
||||||
|
console.log(alertText)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} alertText
|
||||||
|
*/
|
||||||
|
static 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
52
front/src/src/wde/wde-mobile.js
Normal file
52
front/src/src/wde/wde-mobile.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
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()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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) =>{
|
||||||
|
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()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
94
front/src/src/wde/wde.js
Normal file
94
front/src/src/wde/wde.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import WDEApplication from "./application.js"
|
||||||
|
|
||||||
|
export default class AbstractWebDesktopEnvironment{
|
||||||
|
/** @type {Object<string, WDEApplication>} */
|
||||||
|
_applications = {}
|
||||||
|
/** @type {AbstractWebDesktopEnvironment} */
|
||||||
|
#wde
|
||||||
|
|
||||||
|
/** @type {AbstractWebDesktopEnvironment} */
|
||||||
|
_SetWDE(wde){
|
||||||
|
this.#wde = wde
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {Object | undefined} //FIXME
|
||||||
|
*/
|
||||||
|
async _FetchAppManifest(path){
|
||||||
|
// console.log("path: " + path )
|
||||||
|
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
|
||||||
|
await import(/* webpackMode: "eager" */ `${window.location.origin}/res/dev-fs/dist/finder.js`).then((app) => {newApp = app})
|
||||||
|
// let newApp
|
||||||
|
// switch (appManifest.appId) { //FIXME Can't dynamicly load es6 modules withou static pathes
|
||||||
|
// case 'Finder':
|
||||||
|
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
let newAppClass = new newApp.default(this.#wde)
|
||||||
|
this._applications[appManifest.appId] = newAppClass
|
||||||
|
onload()
|
||||||
|
return //TODO return result
|
||||||
|
}
|
||||||
|
|
||||||
|
_GetApp(appId){
|
||||||
|
// console.log(appId)
|
||||||
|
return this._applications[appId]
|
||||||
|
}
|
||||||
|
|
||||||
|
_fetchComp(res) {
|
||||||
|
import(`${window.location.origin}${res}`).then(() => {
|
||||||
|
console.log("Loaded")
|
||||||
|
}, (err)=>{
|
||||||
|
console.log("Error", err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} runContext
|
||||||
|
* @property {boolean} isMobile
|
||||||
|
* @property {string} appPath
|
||||||
|
* @property {string} runPath //TODO
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** //TODO
|
||||||
|
* @typedef {Object} appManifest
|
||||||
|
*/
|
60
front/src/src/wde/widgets/basic-widgets.less
Normal file
60
front/src/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;
|
||||||
|
}
|
134
front/src/src/wde/widgets/file-view/file-view.js
Normal file
134
front/src/src/wde/widgets/file-view/file-view.js
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export default class WDEFileView{
|
||||||
|
path = ""
|
||||||
|
parentElem = undefined
|
||||||
|
selected = []
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} fileViewElem
|
||||||
|
* @param {Function} doubleClickCallback
|
||||||
|
* @param {Function} rightClickCallback
|
||||||
|
* @param {Function} updateFileViewCallback
|
||||||
|
*/
|
||||||
|
constructor(fileViewElem, doubleClickCallback, rightClickCallback, fileUploadCallback, updateFileViewCallback){
|
||||||
|
//TODO check all params
|
||||||
|
this.parentElem = fileViewElem
|
||||||
|
|
||||||
|
fileViewElem.addEventListener('click', (event) => {
|
||||||
|
if (event.target.classList[0] == 'FileTileView')
|
||||||
|
{
|
||||||
|
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
|
||||||
|
WebDesktopEnvironment.Alert("TODO")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let html = await response.text()
|
||||||
|
this.parentElem.innerHTML = html
|
||||||
|
}
|
||||||
|
}
|
86
front/src/src/wde/widgets/file-view/file-view.less
Normal file
86
front/src/src/wde/widgets/file-view/file-view.less
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
.FileTileView{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
131
front/src/src/web-fs/web-fs.js
Normal file
131
front/src/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
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,36 @@
|
|||||||
import WebDesktopEnvironment from "./wde-desktop.js"
|
import AbstractWebDesktopEnvironment from "./wde.js"
|
||||||
|
|
||||||
export default class WDEApplication{
|
export default class WDEApplication{
|
||||||
/** @type {WebDesktopEnvironment} */
|
/** @type {AbstractWebDesktopEnvironment} */
|
||||||
#wde
|
#wde
|
||||||
|
/** @type {string} */
|
||||||
|
AppId
|
||||||
|
//TODO types
|
||||||
|
AppManifest
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {WebDesktopEnvironment} wde
|
* @param {AbstractWebDesktopEnvironment} wde
|
||||||
*/
|
*/
|
||||||
constructor(wde){
|
constructor(wde, AppId, manifest){
|
||||||
this.#wde = wde
|
this.#wde = wde //TODO: Vaidate
|
||||||
|
// console.log(wde)
|
||||||
|
this.AppId = AppId //TODO: Validate
|
||||||
|
this.AppManifest = manifest
|
||||||
|
console.log("SUKA", this.AppId, AppId)
|
||||||
}
|
}
|
||||||
|
|
||||||
getWde(){
|
/** @returns {AbstractWebDesktopEnvironment} */
|
||||||
|
WDE(){
|
||||||
return this.#wde
|
return this.#wde
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async NewWindow(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {Element} */
|
||||||
|
async NewView(){
|
||||||
|
return this.#wde.Decorat.CreateNewView(this.AppId)
|
||||||
|
}
|
||||||
}
|
}
|
@ -3,9 +3,8 @@ export default class DesktopDecorat{
|
|||||||
#windowsLayer
|
#windowsLayer
|
||||||
|
|
||||||
constructor(){
|
constructor(){
|
||||||
this.windowLayer = document.body.querySelector('#windows-layer')
|
this.#windowsLayer = document.body.querySelector('#windows-layer') //TODO Validate if null
|
||||||
// this.#windowsLayer = document.body.querySelector('#windows-layer')
|
|
||||||
this.#windowsLayer = document.body.querySelector('#windows-layer')
|
|
||||||
let startDrag = (event) => {
|
let startDrag = (event) => {
|
||||||
let window = event.target.closest('.WindowFrame')
|
let window = event.target.closest('.WindowFrame')
|
||||||
this.bringWindowToFront(window)
|
this.bringWindowToFront(window)
|
||||||
@ -65,7 +64,6 @@ export default class DesktopDecorat{
|
|||||||
|
|
||||||
document.body.querySelector('#windows-layer').appendChild(newWindow)
|
document.body.querySelector('#windows-layer').appendChild(newWindow)
|
||||||
return newWindow
|
return newWindow
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,8 +3,16 @@ export default class MobileDecorat {
|
|||||||
#applicationsNode
|
#applicationsNode
|
||||||
constructor(){
|
constructor(){
|
||||||
this.#applicationsNode = document.body.querySelector("#mobile-app-views") //TODO validate
|
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
|
* @param {string} appId
|
||||||
* @returns {Element}
|
* @returns {Element}
|
||||||
@ -13,15 +21,17 @@ export default class MobileDecorat {
|
|||||||
let newView = document.createElement("div")
|
let newView = document.createElement("div")
|
||||||
newView.setAttribute("class", "mobile-app-view")
|
newView.setAttribute("class", "mobile-app-view")
|
||||||
newView.setAttribute("appId", appId)
|
newView.setAttribute("appId", appId)
|
||||||
this.#applicationsNode.appendChild(newView)
|
// this.#applicationsNode.appendChild(newView)
|
||||||
|
this.#applicationsNode.insertBefore(newView, this.#applicationsNode.firstChild)
|
||||||
return newView
|
return newView
|
||||||
}
|
}
|
||||||
|
|
||||||
Open(){
|
Open(){
|
||||||
|
|
||||||
}
|
}
|
||||||
BackAction(){
|
BackAction(){
|
||||||
// console.log(this.#applicationsNode.childNodes.length)
|
console.log(this.#applicationsNode.childNodes.length)
|
||||||
if (this.#applicationsNode.childNodes.length <= 1) return
|
if (this.#applicationsNode.childNodes.length <= 1) return
|
||||||
this.#applicationsNode.lastChild.remove()
|
this.#applicationsNode.firstChild.remove()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,7 +15,7 @@ export default class MobileDesktop{
|
|||||||
}
|
}
|
||||||
|
|
||||||
async #createDesktopView(){
|
async #createDesktopView(){
|
||||||
let view = await this.#wde.Decorat.CreateNewView("Sunboard") //FIXME
|
let view = this.#wde.Decorat.CreateNewView("Sunboard") //FIXME
|
||||||
|
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
// path: args[0] //FIXME
|
// path: args[0] //FIXME
|
||||||
@ -28,7 +28,6 @@ export default class MobileDesktop{
|
|||||||
})
|
})
|
||||||
if (response.status != 200){
|
if (response.status != 200){
|
||||||
console.log(response.status)
|
console.log(response.status)
|
||||||
// this.#wde.Alert("Error in render desktop") //TODO
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const html = await response.text()
|
const html = await response.text()
|
||||||
@ -36,11 +35,10 @@ export default class MobileDesktop{
|
|||||||
|
|
||||||
let iconsList = view.querySelectorAll(".app-icon")
|
let iconsList = view.querySelectorAll(".app-icon")
|
||||||
iconsList.forEach(element => {
|
iconsList.forEach(element => {
|
||||||
let appId = element.getAttribute('appId')
|
let path = element.getAttribute('path') //TODO: Validate
|
||||||
|
|
||||||
element.addEventListener('click', () => {
|
element.addEventListener('click', () => {
|
||||||
// console.log(appId)
|
this.#wde.Open(path, [""], "") //FIXME
|
||||||
// this.#wde.Decorat.CreateNewView(appId)
|
|
||||||
this.#wde.Open("/Applications/Finder.app", [""], "")
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,10 @@ import WDEScrollBar from "./scrollbar/scrollbar.js";
|
|||||||
import WebFS from "../web-fs/web-fs.js";
|
import WebFS from "../web-fs/web-fs.js";
|
||||||
import WDEApplication from "./application.js";
|
import WDEApplication from "./application.js";
|
||||||
import WDEFileView from "./widgets/file-view/file-view.js";
|
import WDEFileView from "./widgets/file-view/file-view.js";
|
||||||
|
import AbstractWebDesktopEnvironment from "./wde.js";
|
||||||
|
|
||||||
// import DesktopSunBoard from "./sunboard/sunboard-desktop.js";
|
// import DesktopSunBoard from "./sunboard/sunboard-desktop.js";
|
||||||
export default class WebDesktopEnvironment{
|
export default class WebDesktopEnvironment extends AbstractWebDesktopEnvironment{
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
test = ""
|
test = ""
|
||||||
/** @type {WDEFileView} */
|
/** @type {WDEFileView} */
|
||||||
@ -20,7 +21,10 @@ export default class WebDesktopEnvironment{
|
|||||||
static isMobile = false
|
static isMobile = false
|
||||||
// static decorat
|
// static decorat
|
||||||
static webFs
|
static webFs
|
||||||
|
|
||||||
constructor(){
|
constructor(){
|
||||||
|
super("localhost:8080")
|
||||||
|
super._SetWDE(this)
|
||||||
document.body.style.setProperty('--zoom', 1)
|
document.body.style.setProperty('--zoom', 1)
|
||||||
this.Decorat = new DesktopDecorat()
|
this.Decorat = new DesktopDecorat()
|
||||||
|
|
||||||
@ -31,10 +35,12 @@ export default class WebDesktopEnvironment{
|
|||||||
}
|
}
|
||||||
|
|
||||||
async loadWDE(){
|
async loadWDE(){
|
||||||
|
await this.Open("/Applications/Finder.app", ["/","--desktop", "desktop-layer"])
|
||||||
|
return
|
||||||
|
|
||||||
let autoStart = document.body.querySelector("wde-autostart")
|
let autoStart = document.body.querySelector("wde-autostart")
|
||||||
if (autoStart == null){
|
if (autoStart == null){
|
||||||
WebDesktopEnvironment.Alert("Error in loading DE")
|
WebDesktopEnvironment.Alert("Error in loading DE: Autostart not presented")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for (const child of autoStart.children) {
|
for (const child of autoStart.children) {
|
||||||
@ -64,66 +70,17 @@ export default class WebDesktopEnvironment{
|
|||||||
* @param {string} runPath
|
* @param {string} runPath
|
||||||
*/
|
*/
|
||||||
async Open(appPath, args, runPath){
|
async Open(appPath, args, runPath){
|
||||||
const appManifest = await WebDesktopEnvironment.fetchApp(appPath)
|
|
||||||
|
|
||||||
|
|
||||||
if (appManifest === undefined) return //TODO return err
|
|
||||||
/**@type {runContext} */
|
|
||||||
const runContext = {
|
const runContext = {
|
||||||
WDE: this,
|
|
||||||
isMobile: false,
|
isMobile: false,
|
||||||
bundlePath: appPath,
|
bundlePath: appPath,
|
||||||
runPath: runPath
|
runPath: runPath
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WebDesktopEnvironment.Applications[appManifest.appId] === undefined){
|
super._Open(appPath, args, runPath, (appManifest) =>{
|
||||||
WebDesktopEnvironment.load2(appManifest, () =>{
|
super._GetApp(appManifest.appId).NewWindow(args, runContext)
|
||||||
WebDesktopEnvironment.Applications[appManifest.appId].NewWindow(args, runContext)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
WebDesktopEnvironment.Applications[appManifest.appId].NewWindow(args, runContext)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} appManifest
|
|
||||||
* @param {function} onload callback after script loading
|
|
||||||
*/
|
|
||||||
static async load2(appManifest, onload){
|
|
||||||
// import(window.location.origin + appManifest.js[0]).then((app) => {
|
|
||||||
// console.log(window.location.origin + appManifest.js[0] == 'http://localhost:8080/res/dev-fs/wde/dist/finder.js')
|
|
||||||
// let kek = 'http://localhost:8080/res/dev-fs/wde/dist/finder.js'
|
|
||||||
import('http://localhost:8080/res/dev-fs/dist/finder.js').then((app) => {
|
|
||||||
let newApp = new app.default()
|
|
||||||
// if newApp //TODO Validate
|
|
||||||
WebDesktopEnvironment.Applications[appManifest.appId] = newApp;
|
|
||||||
onload()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return //TODO return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} path
|
|
||||||
* @returns {Object | undefined} //FIXME
|
|
||||||
*/
|
|
||||||
static async fetchApp(path){
|
|
||||||
// console.log("path: " + path )
|
|
||||||
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)
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
//TODO Validate manifest
|
|
||||||
const appManifest = response.json()
|
|
||||||
return appManifest
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} html
|
* @param {string} html
|
||||||
*/
|
*/
|
||||||
@ -178,10 +135,3 @@ export default class WebDesktopEnvironment{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} runContext
|
|
||||||
* @property {WebDesktopEnvironment} WDE
|
|
||||||
* @property {boolean} isMobile
|
|
||||||
* @property {string} appPath
|
|
||||||
* @property {string} runPath //TODO
|
|
||||||
*/
|
|
@ -10,13 +10,14 @@ export default class MobileWebDesktopEnvironment extends AbstractWebDesktopEnvir
|
|||||||
/** @type {MobileSunboard} */
|
/** @type {MobileSunboard} */
|
||||||
#sunBoard
|
#sunBoard
|
||||||
constructor(){
|
constructor(){
|
||||||
|
|
||||||
super()
|
super()
|
||||||
|
super._SetWDE(this)
|
||||||
document.body.style.setProperty('--zoom', 3)
|
document.body.style.setProperty('--zoom', 3)
|
||||||
this.Decorat = new MobileDecorat()
|
this.Decorat = new MobileDecorat()
|
||||||
this.FileView = WDEFileView
|
this.FileView = WDEFileView
|
||||||
this.#sunBoard = new MobileSunboard(this)
|
this.#sunBoard = new MobileSunboard(this)
|
||||||
this.loadWDE()
|
// this.loadWDE()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadWDE(){
|
loadWDE(){
|
||||||
@ -29,17 +30,19 @@ export default class MobileWebDesktopEnvironment extends AbstractWebDesktopEnvir
|
|||||||
* @param {string} runPath
|
* @param {string} runPath
|
||||||
*/
|
*/
|
||||||
async Open(appPath, args, runPath){
|
async Open(appPath, args, runPath){
|
||||||
super._Open(appPath, args, runPath, async (appManifest, runContext) => {
|
const runContext = {
|
||||||
console.log(super._GetApp(appManifest.appId))
|
isMobile: true,
|
||||||
// console.log(super())
|
bundlePath: appPath,
|
||||||
let contentView = await super._GetApp(appManifest.appId).NewWindow(args, runContext)
|
runPath: runPath
|
||||||
let view = this.Decorat.CreateNewView()
|
}
|
||||||
console.log(view)
|
|
||||||
view.appendChild(contentView)
|
super._Open(appPath, args, runPath, (appManifest) =>{
|
||||||
// super._GetApp
|
// console.log(super._GetApp(appManifest.appId))
|
||||||
})
|
super._GetApp(appManifest.appId).NewView(args, runContext)
|
||||||
|
}, this)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#initControlsBar(){
|
#initControlsBar(){
|
||||||
let barNode = document.body.querySelector("#controls-bar")//TODO Validate
|
let barNode = document.body.querySelector("#controls-bar")//TODO Validate
|
||||||
|
|
||||||
|
@ -1,10 +1,24 @@
|
|||||||
import WDEApplication from "./application.js"
|
import WDEApplication from "./application.js"
|
||||||
|
|
||||||
export default class AbstractWebDesktopEnvironment{
|
export default class AbstractWebDesktopEnvironment{
|
||||||
/** @type {Object<string, WDEApplication>} */
|
/** @type {string} */
|
||||||
|
#apiAddress
|
||||||
|
/** @type {Object<string, WDEApplication>} */
|
||||||
_applications = {}
|
_applications = {}
|
||||||
constructor(){
|
/** @type {AbstractWebDesktopEnvironment} */
|
||||||
|
#wde
|
||||||
|
/** @constructor */
|
||||||
|
constructor(apiAddress){
|
||||||
|
this.#apiAddress = apiAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {string} */
|
||||||
|
GetApiAddress(){
|
||||||
|
return `${location.protocol}//${this.#apiAddress}`
|
||||||
|
}
|
||||||
|
/** @type {AbstractWebDesktopEnvironment} */
|
||||||
|
_SetWDE(wde){
|
||||||
|
this.#wde = wde
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,7 +26,8 @@ export default class AbstractWebDesktopEnvironment{
|
|||||||
* @returns {Object | undefined} //FIXME
|
* @returns {Object | undefined} //FIXME
|
||||||
*/
|
*/
|
||||||
async _FetchAppManifest(path){
|
async _FetchAppManifest(path){
|
||||||
console.log("path: " + path )
|
// console.log(location)
|
||||||
|
// console.log(this.GetApiAddress())
|
||||||
const params = new URLSearchParams({path: path, mode: "json"})
|
const params = new URLSearchParams({path: path, mode: "json"})
|
||||||
const response = await fetch(`/system/loadApp?` + params)
|
const response = await fetch(`/system/loadApp?` + params)
|
||||||
if (response.status != 200){
|
if (response.status != 200){
|
||||||
@ -27,28 +42,21 @@ export default class AbstractWebDesktopEnvironment{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} appPath
|
* @param {string} appPath
|
||||||
* @param {string[]} args
|
* @param {runContext} runContext
|
||||||
* @param {string} runPath
|
* @param {string} runPath
|
||||||
* @param {callback} function
|
* @param {function} callback
|
||||||
*/
|
*/
|
||||||
async _Open(appPath, args, runPath, callback){
|
async _Open(appPath, runContext, runPath, callback){
|
||||||
const appManifest = await this._FetchAppManifest(appPath)
|
const appManifest = await this._FetchAppManifest(appPath)
|
||||||
|
|
||||||
if (appManifest === undefined) return //TODO return err
|
if (appManifest === undefined) return //TODO return err
|
||||||
/**@type {runContext} */
|
|
||||||
const runContext = {
|
|
||||||
WDE: this,
|
|
||||||
isMobile: true,
|
|
||||||
bundlePath: appPath,
|
|
||||||
runPath: runPath
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._applications[appManifest.appId] === undefined){
|
if (this._applications[appManifest.appId] === undefined){
|
||||||
this.#loadApp(appManifest, () => {
|
this.#loadApp(appManifest, () => {
|
||||||
callback(appManifest, runContext)
|
callback(appManifest)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
callback(appManifest, runContext)
|
callback(appManifest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,22 +65,35 @@ export default class AbstractWebDesktopEnvironment{
|
|||||||
* @param {function} onload callback after script loading
|
* @param {function} onload callback after script loading
|
||||||
*/
|
*/
|
||||||
async #loadApp(appManifest, onload){
|
async #loadApp(appManifest, onload){
|
||||||
|
let newApp
|
||||||
// console.log(appManifest)
|
// console.log(appManifest)
|
||||||
// import(window.location.origin + appManifest.js[0]).then((app) => {
|
await import(appManifest.js[0]).then((app) => {newApp = app})
|
||||||
// console.log(window.location.origin + appManifest.js[0] == 'http://localhost:8080/res/dev-fs/wde/dist/finder.js')
|
let newAppClass = new newApp.default(this.#wde, appManifest)
|
||||||
// let kek = 'http://localhost:8080/res/dev-fs/wde/dist/finder.js'
|
this._applications[appManifest.appId] = newAppClass
|
||||||
import('http://localhost:8080/res/dev-fs/dist/finder.js').then((app) => {
|
|
||||||
let newApp = new app.default()
|
|
||||||
// if newApp //TODO Validate
|
|
||||||
this._applications[appManifest.appId] = newApp;
|
|
||||||
onload()
|
|
||||||
})
|
|
||||||
|
|
||||||
|
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
|
return //TODO return result
|
||||||
}
|
}
|
||||||
|
|
||||||
_GetApp(appId){
|
_GetApp(appId){
|
||||||
console.log(appId)
|
// console.log(appId)
|
||||||
return this._applications[appId]
|
return this._applications[appId]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} runContext
|
||||||
|
* @property {boolean} isMobile
|
||||||
|
* @property {string} appPath
|
||||||
|
* @property {string} runPath //TODO
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** //TODO
|
||||||
|
* @typedef {Object} appManifest
|
||||||
|
*/
|
@ -1,16 +1,20 @@
|
|||||||
|
import AbstractWebDesktopEnvironment from "../../wde.js"
|
||||||
|
|
||||||
|
|
||||||
export default class WDEFileView{
|
export default class WDEFileView{
|
||||||
path = ""
|
path = ""
|
||||||
parentElem = undefined
|
parentElem = undefined
|
||||||
selected = []
|
selected = []
|
||||||
|
/** @type {AbstractWebDesktopEnvironment} */
|
||||||
|
#wde
|
||||||
/**
|
/**
|
||||||
* @param {HTMLElement} fileViewElem
|
* @param {HTMLElement} fileViewElem
|
||||||
* @param {Function} doubleClickCallback
|
* @param {Function} doubleClickCallback
|
||||||
* @param {Function} rightClickCallback
|
* @param {Function} rightClickCallback
|
||||||
* @param {Function} updateFileViewCallback
|
* @param {Function} updateFileViewCallback
|
||||||
*/
|
*/
|
||||||
constructor(fileViewElem, doubleClickCallback, rightClickCallback, fileUploadCallback, updateFileViewCallback){
|
constructor(fileViewElem, doubleClickCallback, rightClickCallback, fileUploadCallback, updateFileViewCallback, wde){
|
||||||
|
this.#wde = wde
|
||||||
//TODO check all params
|
//TODO check all params
|
||||||
this.parentElem = fileViewElem
|
this.parentElem = fileViewElem
|
||||||
|
|
||||||
@ -122,7 +126,7 @@ export default class WDEFileView{
|
|||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
path: path
|
path: path
|
||||||
})
|
})
|
||||||
const response = await fetch(`/system/wde/widgets/file-tile-view?` + params)
|
const response = await fetch(`${this.#wde.GetApiAddress()}/system/wde/widgets/file-tile-view?` + params)
|
||||||
if (response.status != 200){
|
if (response.status != 200){
|
||||||
//TODO Error text message
|
//TODO Error text message
|
||||||
WebDesktopEnvironment.Alert("TODO")
|
WebDesktopEnvironment.Alert("TODO")
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
// Generated using webpack-cli https://github.com/webpack/webpack-cli
|
|
||||||
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const isProduction = process.env.NODE_ENV == 'production';
|
|
||||||
|
|
||||||
|
|
||||||
const stylesHandler = 'style-loader';
|
|
||||||
|
|
||||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
|
||||||
const { experiments } = require('webpack');
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
// entry: [ './src/wde-mobile.js'],
|
|
||||||
entry: {
|
|
||||||
desktop:[
|
|
||||||
'./src/wde/wde-desktop.js',
|
|
||||||
],
|
|
||||||
desktop_style: [
|
|
||||||
"./src/desktop.less",
|
|
||||||
],
|
|
||||||
mobile: [
|
|
||||||
'./src/wde/wde-mobile.js',
|
|
||||||
],
|
|
||||||
mobile_style: [
|
|
||||||
"./src/mobile.less",
|
|
||||||
],
|
|
||||||
finder : [
|
|
||||||
'./src/apps/finder/finder.js',
|
|
||||||
],
|
|
||||||
finder_style:[
|
|
||||||
'./src/apps/finder/finder.less',
|
|
||||||
]
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
// path: path.resolve(__dirname, 'dist'),
|
|
||||||
path: path.resolve('../res/dev-fs/dist'),
|
|
||||||
filename: '[name].js',
|
|
||||||
library: {
|
|
||||||
type: "module",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
experiments: {
|
|
||||||
outputModule: true,
|
|
||||||
},
|
|
||||||
devServer: {
|
|
||||||
open: true,
|
|
||||||
host: 'localhost',
|
|
||||||
},
|
|
||||||
plugins: [new MiniCssExtractPlugin()],
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.(js|jsx)$/i,
|
|
||||||
loader: 'babel-loader',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.css$/i,
|
|
||||||
use: [stylesHandler,'css-loader'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.less$/i,
|
|
||||||
// use: [stylesHandler, 'css-loader', 'less-loader'],
|
|
||||||
use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
|
|
||||||
type: 'asset',
|
|
||||||
},
|
|
||||||
|
|
||||||
// Add your rules for custom modules here
|
|
||||||
// Learn more about loaders from https://webpack.js.org/loaders/
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
module.exports = () => {
|
|
||||||
if (isProduction) {
|
|
||||||
config.mode = 'production';
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
config.mode = 'development';
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
};
|
|
147
res/dev-fs/dist/desktop.js
vendored
147
res/dev-fs/dist/desktop.js
vendored
File diff suppressed because one or more lines are too long
384
res/dev-fs/dist/desktop_style.css
vendored
384
res/dev-fs/dist/desktop_style.css
vendored
@ -1,384 +0,0 @@
|
|||||||
/*!***********************************************************************************************************!*\
|
|
||||||
!*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/less-loader/dist/cjs.js!./src/desktop.less ***!
|
|
||||||
\***********************************************************************************************************/
|
|
||||||
.WdePrimitives.AdjectiveElement {
|
|
||||||
border: 1px solid #555555;
|
|
||||||
}
|
|
||||||
.FileTileView {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
/* @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;
|
|
||||||
}
|
|
||||||
|
|
45
res/dev-fs/dist/desktop_style.js
vendored
45
res/dev-fs/dist/desktop_style.js
vendored
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
|
|
||||||
* This devtool is neither made for production nor for readable output files.
|
|
||||||
* It uses "eval()" calls to create a separate source file in the browser devtools.
|
|
||||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
|
||||||
* or disable the default devtool with "devtool: false".
|
|
||||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
|
||||||
*/
|
|
||||||
/******/ var __webpack_modules__ = ({
|
|
||||||
|
|
||||||
/***/ "./src/desktop.less":
|
|
||||||
/*!**************************!*\
|
|
||||||
!*** ./src/desktop.less ***!
|
|
||||||
\**************************/
|
|
||||||
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
||||||
|
|
||||||
eval("__webpack_require__.r(__webpack_exports__);\n// extracted by mini-css-extract-plugin\n\n\n//# sourceURL=webpack://my-webpack-project/./src/desktop.less?");
|
|
||||||
|
|
||||||
/***/ })
|
|
||||||
|
|
||||||
/******/ });
|
|
||||||
/************************************************************************/
|
|
||||||
/******/ // The require scope
|
|
||||||
/******/ var __webpack_require__ = {};
|
|
||||||
/******/
|
|
||||||
/************************************************************************/
|
|
||||||
/******/ /* webpack/runtime/make namespace object */
|
|
||||||
/******/ (() => {
|
|
||||||
/******/ // define __esModule on exports
|
|
||||||
/******/ __webpack_require__.r = (exports) => {
|
|
||||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
||||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
||||||
/******/ }
|
|
||||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
||||||
/******/ };
|
|
||||||
/******/ })();
|
|
||||||
/******/
|
|
||||||
/************************************************************************/
|
|
||||||
/******/
|
|
||||||
/******/ // startup
|
|
||||||
/******/ // Load entry module and return exports
|
|
||||||
/******/ // This entry module can't be inlined because the eval devtool is used.
|
|
||||||
/******/ var __webpack_exports__ = {};
|
|
||||||
/******/ __webpack_modules__["./src/desktop.less"](0, __webpack_exports__, __webpack_require__);
|
|
||||||
/******/
|
|
35
res/dev-fs/dist/finder.css
vendored
35
res/dev-fs/dist/finder.css
vendored
@ -1,35 +0,0 @@
|
|||||||
/*!**********************************************************************************************************************!*\
|
|
||||||
!*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/less-loader/dist/cjs.js!./src/apps/finder/finder.less ***!
|
|
||||||
\**********************************************************************************************************************/
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
|
|
167
res/dev-fs/dist/finder.js
vendored
167
res/dev-fs/dist/finder.js
vendored
File diff suppressed because one or more lines are too long
35
res/dev-fs/dist/finder_style.css
vendored
35
res/dev-fs/dist/finder_style.css
vendored
@ -1,35 +0,0 @@
|
|||||||
/*!**********************************************************************************************************************!*\
|
|
||||||
!*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/less-loader/dist/cjs.js!./src/apps/finder/finder.less ***!
|
|
||||||
\**********************************************************************************************************************/
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
|
|
45
res/dev-fs/dist/finder_style.js
vendored
45
res/dev-fs/dist/finder_style.js
vendored
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
|
|
||||||
* This devtool is neither made for production nor for readable output files.
|
|
||||||
* It uses "eval()" calls to create a separate source file in the browser devtools.
|
|
||||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
|
||||||
* or disable the default devtool with "devtool: false".
|
|
||||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
|
||||||
*/
|
|
||||||
/******/ var __webpack_modules__ = ({
|
|
||||||
|
|
||||||
/***/ "./src/apps/finder/finder.less":
|
|
||||||
/*!*************************************!*\
|
|
||||||
!*** ./src/apps/finder/finder.less ***!
|
|
||||||
\*************************************/
|
|
||||||
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
||||||
|
|
||||||
eval("__webpack_require__.r(__webpack_exports__);\n// extracted by mini-css-extract-plugin\n\n\n//# sourceURL=webpack://my-webpack-project/./src/apps/finder/finder.less?");
|
|
||||||
|
|
||||||
/***/ })
|
|
||||||
|
|
||||||
/******/ });
|
|
||||||
/************************************************************************/
|
|
||||||
/******/ // The require scope
|
|
||||||
/******/ var __webpack_require__ = {};
|
|
||||||
/******/
|
|
||||||
/************************************************************************/
|
|
||||||
/******/ /* webpack/runtime/make namespace object */
|
|
||||||
/******/ (() => {
|
|
||||||
/******/ // define __esModule on exports
|
|
||||||
/******/ __webpack_require__.r = (exports) => {
|
|
||||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
||||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
||||||
/******/ }
|
|
||||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
||||||
/******/ };
|
|
||||||
/******/ })();
|
|
||||||
/******/
|
|
||||||
/************************************************************************/
|
|
||||||
/******/
|
|
||||||
/******/ // startup
|
|
||||||
/******/ // Load entry module and return exports
|
|
||||||
/******/ // This entry module can't be inlined because the eval devtool is used.
|
|
||||||
/******/ var __webpack_exports__ = {};
|
|
||||||
/******/ __webpack_modules__["./src/apps/finder/finder.less"](0, __webpack_exports__, __webpack_require__);
|
|
||||||
/******/
|
|
187
res/dev-fs/dist/mobile.js
vendored
187
res/dev-fs/dist/mobile.js
vendored
File diff suppressed because one or more lines are too long
93
res/dev-fs/dist/mobile_style.css
vendored
93
res/dev-fs/dist/mobile_style.css
vendored
@ -1,93 +0,0 @@
|
|||||||
/*!**********************************************************************************************************!*\
|
|
||||||
!*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/less-loader/dist/cjs.js!./src/mobile.less ***!
|
|
||||||
\**********************************************************************************************************/
|
|
||||||
.WdePrimitives.AdjectiveElement,
|
|
||||||
#controls-bar {
|
|
||||||
border: 1px solid #555555;
|
|
||||||
}
|
|
||||||
#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: #9999CC;
|
|
||||||
}
|
|
||||||
.apps-list {
|
|
||||||
/* Auto layout */
|
|
||||||
display: flex;
|
|
||||||
padding: 64px 32px;
|
|
||||||
align-items: flex-start;
|
|
||||||
align-content: flex-start;
|
|
||||||
gap: 103px 18px;
|
|
||||||
flex: 1 0 0;
|
|
||||||
align-self: stretch;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.app-icon {
|
|
||||||
width: 100px;
|
|
||||||
height: 100px;
|
|
||||||
/* Auto layout */
|
|
||||||
display: flex;
|
|
||||||
padding: 4px 8px;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
.app-icon .icon {
|
|
||||||
width: 64px;
|
|
||||||
height: 64px;
|
|
||||||
background-color: beige;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
/* Auto layout */
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
#mobile-app-views {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
#controls-bar {
|
|
||||||
width: 100%;
|
|
||||||
height: 150px;
|
|
||||||
background-color: #C0C0C0;
|
|
||||||
/* Auto layout */
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
.mobile-app-view {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
45
res/dev-fs/dist/mobile_style.js
vendored
45
res/dev-fs/dist/mobile_style.js
vendored
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
|
|
||||||
* This devtool is neither made for production nor for readable output files.
|
|
||||||
* It uses "eval()" calls to create a separate source file in the browser devtools.
|
|
||||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
|
||||||
* or disable the default devtool with "devtool: false".
|
|
||||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
|
||||||
*/
|
|
||||||
/******/ var __webpack_modules__ = ({
|
|
||||||
|
|
||||||
/***/ "./src/mobile.less":
|
|
||||||
/*!*************************!*\
|
|
||||||
!*** ./src/mobile.less ***!
|
|
||||||
\*************************/
|
|
||||||
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
||||||
|
|
||||||
eval("__webpack_require__.r(__webpack_exports__);\n// extracted by mini-css-extract-plugin\n\n\n//# sourceURL=webpack://my-webpack-project/./src/mobile.less?");
|
|
||||||
|
|
||||||
/***/ })
|
|
||||||
|
|
||||||
/******/ });
|
|
||||||
/************************************************************************/
|
|
||||||
/******/ // The require scope
|
|
||||||
/******/ var __webpack_require__ = {};
|
|
||||||
/******/
|
|
||||||
/************************************************************************/
|
|
||||||
/******/ /* webpack/runtime/make namespace object */
|
|
||||||
/******/ (() => {
|
|
||||||
/******/ // define __esModule on exports
|
|
||||||
/******/ __webpack_require__.r = (exports) => {
|
|
||||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
||||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
||||||
/******/ }
|
|
||||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
||||||
/******/ };
|
|
||||||
/******/ })();
|
|
||||||
/******/
|
|
||||||
/************************************************************************/
|
|
||||||
/******/
|
|
||||||
/******/ // startup
|
|
||||||
/******/ // Load entry module and return exports
|
|
||||||
/******/ // This entry module can't be inlined because the eval devtool is used.
|
|
||||||
/******/ var __webpack_exports__ = {};
|
|
||||||
/******/ __webpack_modules__["./src/mobile.less"](0, __webpack_exports__, __webpack_require__);
|
|
||||||
/******/
|
|
@ -30,6 +30,18 @@ func PrivateRoutes(port string, webfs *webfilesystem.WebFileSystem, webde *wde.W
|
|||||||
router.Use(favicon.New("./res/dev-fs/wde/icons/ohno.png"))
|
router.Use(favicon.New("./res/dev-fs/wde/icons/ohno.png"))
|
||||||
router.LoadHTMLGlob("templates/**/*")
|
router.LoadHTMLGlob("templates/**/*")
|
||||||
router.Static("/res", "res")
|
router.Static("/res", "res")
|
||||||
|
router.Static("/front", "./front/")
|
||||||
|
// router.Use(cors.New(cors.Config{
|
||||||
|
// AllowOrigins: []string{"http://localhost:1234"},
|
||||||
|
// AllowMethods: []string{"PUT", "PATCH"},
|
||||||
|
// AllowHeaders: []string{"Origin"},
|
||||||
|
// ExposeHeaders: []string{"Content-Length"},
|
||||||
|
// AllowCredentials: true,
|
||||||
|
// AllowOriginFunc: func(origin string) bool {
|
||||||
|
// return origin == "http://localhost:1234"
|
||||||
|
// },
|
||||||
|
// MaxAge: 12 * time.Hour,
|
||||||
|
// }))
|
||||||
// Set a lower memory limit for multipart forms (default is 32 MiB)
|
// Set a lower memory limit for multipart forms (default is 32 MiB)
|
||||||
router.MaxMultipartMemory = 8 << 20 // 8 MiB
|
router.MaxMultipartMemory = 8 << 20 // 8 MiB
|
||||||
|
|
||||||
|
@ -21,12 +21,15 @@
|
|||||||
<script src="/res/dev-fs/wde/wde-scrollbar.js"></script>
|
<script src="/res/dev-fs/wde/wde-scrollbar.js"></script>
|
||||||
<script src="/res/dev-fs/wde/file-view.js"></script> -->
|
<script src="/res/dev-fs/wde/file-view.js"></script> -->
|
||||||
<!-- <script src="res/dev-fs/wde/dist/desktop.js"></script> -->
|
<!-- <script src="res/dev-fs/wde/dist/desktop.js"></script> -->
|
||||||
<link rel="stylesheet" type="text/css" href="/res/dev-fs/dist/desktop_style.css">
|
|
||||||
<link rel="stylesheet" type="text/css" href="/res/dev-fs/dist/finder_style.css">
|
<!-- <link rel="stylesheet" type="text/css" href="/res/dev-fs/dist/desktop_style.css"> -->
|
||||||
|
<!-- <link rel="stylesheet" type="text/css" href="/res/dev-fs/dist/finder_style.css"> -->
|
||||||
|
<link rel="stylesheet" href="/front/dist/desktop.css">
|
||||||
|
<!-- <link rel="stylesheet" href="/front/dist/apps/finder/finder.css"> -->
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import * as WebDesktopEnvironment from '/res/dev-fs/dist/desktop.js';
|
import * as WebDesktopEnvironment from "/front/src/wde/wde-desktop.js"
|
||||||
// console.log(WebDesktopEnvironment)
|
// console.log(WebDesktopEnvironment)
|
||||||
let kek = new WebDesktopEnvironment.default()
|
let kek = new WebDesktopEnvironment.default()
|
||||||
</script>
|
</script>
|
||||||
|
@ -3,13 +3,14 @@
|
|||||||
<title>Greg Brzezinski</title>
|
<title>Greg Brzezinski</title>
|
||||||
<head>
|
<head>
|
||||||
<!-- <script src="res/dev-fs/dist/mobile.js"></script> -->
|
<!-- <script src="res/dev-fs/dist/mobile.js"></script> -->
|
||||||
<link rel="stylesheet" type="text/css" href="res/dev-fs/dist/mobile_style.css">
|
<link rel="stylesheet" href="/front/dist/mobile.css">
|
||||||
|
<!-- <link rel="stylesheet" href="/front/dist/apps/finder/finder.css"> -->
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import * as WebDesktopEnvironment from '/res/dev-fs/dist/mobile.js';
|
import * as wde from '/front/src/wde/wde-mobile.js';
|
||||||
// console.log(WebDesktopEnvironment)
|
// console.log(WebDesktopEnvironment)
|
||||||
let kek = new WebDesktopEnvironment.default()
|
let kek = new wde.default()
|
||||||
</script>
|
</script>
|
||||||
<!-- <div id="mobile-sunboard">
|
<!-- <div id="mobile-sunboard">
|
||||||
</div> -->
|
</div> -->
|
||||||
@ -17,16 +18,16 @@
|
|||||||
<div id="controls-bar">
|
<div id="controls-bar">
|
||||||
<div id="back" class="app-icon Click" >
|
<div id="back" class="app-icon Click" >
|
||||||
<img class="icon NoClick" src="">
|
<img class="icon NoClick" src="">
|
||||||
<div class="lable NoClick">Test</div>
|
<div class="lable NoClick">Back</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-icon Click" >
|
<!-- <div class="app-icon Click" >
|
||||||
<img class="icon NoClick" src="">
|
<img class="icon NoClick" src="">
|
||||||
<div class="lable NoClick">Test</div>
|
<div class="lable NoClick">Test</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-icon Click" >
|
<div class="app-icon Click" >
|
||||||
<img class="icon NoClick" src="">
|
<img class="icon NoClick" src="">
|
||||||
<div class="lable NoClick">Test</div>
|
<div class="lable NoClick">Test</div>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
51
templates/personal-properties/mobile-app.html
Normal file
51
templates/personal-properties/mobile-app.html
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
{{ define "personal-properties/mobile-app.tmpl" }}
|
||||||
|
<div class="ContentBorder AdjectiveElement">
|
||||||
|
<div class="PersPropsContent">
|
||||||
|
<div class="PropsView">
|
||||||
|
<div class="PropertiesList">
|
||||||
|
<div class="Links">
|
||||||
|
{{ range $link := .Links }}
|
||||||
|
<a href="{{$link.Url}}" target="_blank">
|
||||||
|
<img class="Link" src="/system/libs/img/get?path={{$link.Icon}}" alt="{{$link.Text}}">
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
<div class="ShortBio">
|
||||||
|
<img class="Image" src="/system/libs/img/get?path={{ .HeaderProps.IconPath }}" alt="My Photo">
|
||||||
|
<div class="Text">
|
||||||
|
<div class="Name">{{ .HeaderProps.Name }}</div>
|
||||||
|
<div>{{ .HeaderProps.Value1 }}</div>
|
||||||
|
<div>{{ .HeaderProps.Value2 }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ range $island := .Islands }}
|
||||||
|
<!-- FIXME -->
|
||||||
|
<div class="Island">
|
||||||
|
<div class="Title"> {{$island.Header}}:</div>
|
||||||
|
<div class="Content">
|
||||||
|
{{range $property := $island.Properties}}
|
||||||
|
<div class="Row">
|
||||||
|
<div class="Key">
|
||||||
|
{{$property.Key}}:
|
||||||
|
{{ range $keyComment := $property.KeyComments }}
|
||||||
|
<div class="KeyComment">{{ $keyComment }}</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
<div class="Values">
|
||||||
|
{{ range $value := $property.Values }}
|
||||||
|
<div class="Value">{{ $value }}</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- {{template "wde-widgets/scrollbar.tmpl" .}} -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
|||||||
{{ define "personal-properties/mobile-app.tmpl" }}
|
|
||||||
<div class="MobileContentBorder">
|
|
||||||
<div class="ScrollContent">
|
|
||||||
<div class="PropertiesList">
|
|
||||||
<div class="Personal-properties-bio">
|
|
||||||
<img src="res/img/default-avatar-photo-placeholder-profile-picture-vector.jpg" alt="My Photo" style="width: 48px;height: 48px;">
|
|
||||||
<div class="Personal-properties-textbio">
|
|
||||||
<div>{{ .Name }}</div>
|
|
||||||
<div>{{ .BasicBio }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ range $propIsland := .allprops }}
|
|
||||||
<div id="prop" class="Personal-properties-prop">
|
|
||||||
<div class="Personal-properties-prop-title">
|
|
||||||
{{$propIsland.Header}}:
|
|
||||||
</div>
|
|
||||||
<div class="Personal-properties-prop-content">
|
|
||||||
{{range $prop := $propIsland.Props}}
|
|
||||||
<div class="Personal-properties-prop-row">
|
|
||||||
<div class="Personal-properties-prop-key">
|
|
||||||
{{$prop.Key}}:
|
|
||||||
{{ range $value := $prop.KeyComments }}
|
|
||||||
<div class="Personal-properties-prop-key-comments">
|
|
||||||
{{ $value }}
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
</div>
|
|
||||||
<div class="Personal-properties-prop-values">
|
|
||||||
{{ range $value := $prop.Values }}
|
|
||||||
<div class="Personal-properties-prop-value">
|
|
||||||
{{ $value }}
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
|||||||
<div id="icons">
|
<div id="icons">
|
||||||
<div class="apps-list NoClick">
|
<div class="apps-list NoClick">
|
||||||
{{ range $appIcon := .AppsIcons }}
|
{{ range $appIcon := .AppsIcons }}
|
||||||
<div fileType="{{ $appIcon.Type }}" class="app-icon Click" appId="{{$appIcon.AppId}}" name="{{$appIcon.Lable}}">
|
<div fileType="{{ $appIcon.Type }}" path="{{$appIcon.Path}}"class="app-icon Click" appId="{{$appIcon.AppId}}" name="{{$appIcon.Lable}}">
|
||||||
<!-- <div class="Icon NoClick"></div> -->
|
<!-- <div class="Icon NoClick"></div> -->
|
||||||
<img class="icon NoClick" src="{{ $appIcon.Icon }}">
|
<img class="icon NoClick" src="{{ $appIcon.Icon }}">
|
||||||
<div class="lable NoClick">{{ $appIcon.Lable }}</div>
|
<div class="lable NoClick">{{ $appIcon.Lable }}</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user