2017-08-07 00:49:24 +02:00
|
|
|
self.OS.GUI =
|
2018-01-26 18:57:28 +01:00
|
|
|
dialogs: new Object()
|
|
|
|
dialog: undefined
|
2017-08-24 01:53:13 +02:00
|
|
|
htmlToScheme: (html, app, parent) ->
|
|
|
|
scheme = $.parseHTML html
|
|
|
|
($ parent).append scheme
|
|
|
|
riot.mount ($ scheme), { observable: app.observable }
|
|
|
|
app.scheme = scheme[0]
|
|
|
|
app.main()
|
|
|
|
app.show()
|
2017-08-16 00:27:32 +02:00
|
|
|
loadScheme: (path, app, parent) ->
|
2017-08-15 02:56:04 +02:00
|
|
|
_API.get path,
|
2017-08-14 00:20:19 +02:00
|
|
|
(x) ->
|
2017-08-11 01:58:46 +02:00
|
|
|
return null unless x
|
2017-08-24 01:53:13 +02:00
|
|
|
_GUI.htmlToScheme x, app, parent
|
2017-08-26 16:50:13 +02:00
|
|
|
, (e, s) ->
|
2018-01-29 19:16:29 +01:00
|
|
|
_courrier.osfail "Cannot load scheme file: #{path} for #{app.name} (#{app.pid})", e, s
|
2017-08-27 23:40:02 +02:00
|
|
|
|
|
|
|
clearTheme: () ->
|
|
|
|
$ "head link#ostheme"
|
|
|
|
.attr "href", ""
|
2017-08-14 00:20:19 +02:00
|
|
|
|
2018-01-26 18:57:28 +01:00
|
|
|
loadTheme: (name, force) ->
|
|
|
|
_GUI.clearTheme() if force
|
2017-08-07 00:49:24 +02:00
|
|
|
path = "resources/themes/#{name}/#{name}.css"
|
2017-08-11 01:58:46 +02:00
|
|
|
$ "head link#ostheme"
|
|
|
|
.attr "href", path
|
2017-08-14 00:20:19 +02:00
|
|
|
|
2017-08-16 00:27:32 +02:00
|
|
|
pushServices: (srvs) ->
|
|
|
|
f = (v) ->
|
|
|
|
_courrier.observable.one "srvroutineready", () -> _GUI.pushService v
|
|
|
|
_GUI.pushService srvs[0]
|
|
|
|
srvs.splice 0, 1
|
|
|
|
f i for i in srvs
|
|
|
|
|
2018-01-26 18:57:28 +01:00
|
|
|
openDialog: (d, f, title, data) ->
|
|
|
|
if _GUI.dialog
|
|
|
|
_GUI.dialog.show()
|
|
|
|
return
|
|
|
|
if not _GUI.dialogs[d]
|
|
|
|
ex = _API.throwe "Dialog"
|
|
|
|
return _courrier.oserror "Dialog #{d} not found", ex, null
|
|
|
|
_GUI.dialog = new _GUI.dialogs[d]()
|
|
|
|
_GUI.dialog.parent = _GUI
|
|
|
|
_GUI.dialog.handler = f
|
|
|
|
_GUI.dialog.pid = -1
|
|
|
|
_GUI.dialog.data = data
|
|
|
|
_GUI.dialog.title = title
|
|
|
|
_GUI.dialog.init()
|
|
|
|
|
2018-01-22 19:59:08 +01:00
|
|
|
pushService: (ph) ->
|
|
|
|
arr = ph.split "/"
|
|
|
|
srv = arr[1]
|
|
|
|
app = arr[0]
|
2017-08-27 23:40:02 +02:00
|
|
|
return _PM.createProcess srv, _OS.APP[srv] if _OS.APP[srv]
|
2018-01-22 19:59:08 +01:00
|
|
|
_GUI.loadApp app,
|
2018-01-24 01:03:14 +01:00
|
|
|
(a) ->
|
2018-01-22 19:59:08 +01:00
|
|
|
return _PM.createProcess srv, _OS.APP[srv] if _OS.APP[srv]
|
|
|
|
(e, s) ->
|
2017-08-16 00:27:32 +02:00
|
|
|
_courrier.trigger "srvroutineready", srv
|
2017-08-27 23:40:02 +02:00
|
|
|
_courrier.osfail "Cannot read service script: #{srv} ", e, s
|
2018-01-22 19:59:08 +01:00
|
|
|
|
2018-01-26 18:57:28 +01:00
|
|
|
appsByMime: (mime) ->
|
2018-01-28 02:01:21 +01:00
|
|
|
metas = ( a.meta for k, a of _OS.APP when a and a.type is 1)
|
|
|
|
mimes = ( m.mimes for m in metas when m)
|
2018-01-26 18:57:28 +01:00
|
|
|
apps = []
|
|
|
|
# search app by mimes
|
|
|
|
f = ( arr, idx ) ->
|
2018-01-28 02:01:21 +01:00
|
|
|
try
|
|
|
|
arr.filter (m, i) ->
|
|
|
|
if mime.match (new RegExp m, "g")
|
|
|
|
apps.push metas[idx]
|
|
|
|
return false
|
2018-01-26 18:57:28 +01:00
|
|
|
return false
|
2018-01-28 02:01:21 +01:00
|
|
|
catch e
|
|
|
|
_courrier.osfail "Find app by mimes #{mime}", e, mime
|
2018-01-26 18:57:28 +01:00
|
|
|
|
2018-01-26 19:10:00 +01:00
|
|
|
( f m, i if m ) for m, i in mimes
|
2018-01-26 18:57:28 +01:00
|
|
|
return apps
|
|
|
|
|
|
|
|
openWith: (it) ->
|
|
|
|
return unless it
|
|
|
|
console.log "open #{it.path}"
|
|
|
|
apps = _GUI.appsByMime ( if it.type is "dir" then "dir" else it.mime )
|
|
|
|
return OS.info "No application available to open #{it.filename}" if apps.length is 0
|
|
|
|
return _GUI.launch apps[0].app, [it.path] if apps.length is 1
|
|
|
|
list = ( { text: e.app, icon: e.icon, iconclass: e.iconclass } for e in apps )
|
|
|
|
_GUI.openDialog "SelectionDialog", ( d ) ->
|
|
|
|
_GUI.launch d.text, [it.path]
|
|
|
|
, "Open width", list
|
|
|
|
|
2017-08-27 23:40:02 +02:00
|
|
|
forceLaunch: (app, args) ->
|
|
|
|
console.log "This method is used for developing only, please use the launch method instead"
|
|
|
|
_PM.killAll app
|
|
|
|
_OS.APP[app] = undefined
|
|
|
|
_GUI.launch app, args
|
|
|
|
|
2018-01-24 01:03:14 +01:00
|
|
|
loadApp: (app, ok, err) ->
|
2018-01-22 19:59:08 +01:00
|
|
|
path = "packages/#{app}/"
|
|
|
|
_API.script path + "main.js",
|
|
|
|
(d) ->
|
|
|
|
#load css file
|
|
|
|
_API.get "#{path}main.css",
|
|
|
|
() ->
|
|
|
|
$ '<link>', { rel: 'stylesheet', type: 'text/css', 'href': "#{path}main.css" }
|
|
|
|
.appendTo 'head'
|
|
|
|
, () ->
|
|
|
|
#launch
|
|
|
|
if _OS.APP[app]
|
|
|
|
# load app meta data
|
|
|
|
_API.get "#{path}package.json",
|
|
|
|
(data) ->
|
|
|
|
_OS.APP[app].meta = data
|
|
|
|
ok app
|
|
|
|
, (e, s) ->
|
|
|
|
_courrier.osfail "Cannot read application metadata: #{app}", e, s
|
|
|
|
err e, s
|
|
|
|
else
|
|
|
|
ok app
|
|
|
|
, (e, s) ->
|
|
|
|
#BUG report here
|
|
|
|
_courrier.osfail "Cannot load application script: #{app}", e, s
|
|
|
|
console.log "bug report", e, s, path
|
|
|
|
err e,s
|
2017-08-27 23:40:02 +02:00
|
|
|
launch: (app, args) ->
|
|
|
|
if not _OS.APP[app]
|
2017-08-11 01:58:46 +02:00
|
|
|
# first load it
|
2018-01-22 19:59:08 +01:00
|
|
|
_GUI.loadApp app,
|
|
|
|
(a)->
|
|
|
|
_PM.createProcess a, _OS.APP[a], args
|
2017-08-26 16:50:13 +02:00
|
|
|
, (e, s) ->
|
2017-08-11 01:58:46 +02:00
|
|
|
else
|
2017-08-14 00:20:19 +02:00
|
|
|
# now launch it
|
2017-08-27 23:40:02 +02:00
|
|
|
if _OS.APP[app]
|
|
|
|
_PM.createProcess app, _OS.APP[app], args
|
2017-08-26 16:50:13 +02:00
|
|
|
dock: (app, meta) ->
|
2017-08-14 00:20:19 +02:00
|
|
|
# dock an application to a dock
|
|
|
|
# create a data object
|
2017-08-15 02:56:04 +02:00
|
|
|
data =
|
|
|
|
icon: null
|
|
|
|
iconclass: meta.iconclass || ""
|
2017-08-26 16:50:13 +02:00
|
|
|
app: app
|
|
|
|
onbtclick: () -> app.toggle()
|
2017-08-14 00:20:19 +02:00
|
|
|
data.icon = "packages/#{meta.app}/#{meta.icon}" if meta.icon
|
2017-08-26 16:50:13 +02:00
|
|
|
# TODO: add default app icon class in system setting
|
|
|
|
# so that it can be themed
|
2017-08-14 00:20:19 +02:00
|
|
|
data.iconclass = "fa fa-cogs" if (not meta.icon) and (not meta.iconclass)
|
|
|
|
dock = $ "#sysdock"
|
2017-08-26 16:50:13 +02:00
|
|
|
app.one "rendered", () ->
|
|
|
|
dock.get(0).newapp data
|
|
|
|
app.sysdock = dock.get(0)
|
|
|
|
app.appmenu = ($ "[data-id = 'appmenu']", "#syspanel")[0]
|
2017-08-14 00:20:19 +02:00
|
|
|
app.init()
|
|
|
|
|
|
|
|
undock: (app) ->
|
|
|
|
($ "#sysdock").get(0).removeapp app
|
|
|
|
|
2017-08-15 02:56:04 +02:00
|
|
|
attachservice: (srv) ->
|
|
|
|
($ "#syspanel")[0].attachservice srv
|
|
|
|
srv.init()
|
|
|
|
detachservice: (srv) ->
|
|
|
|
($ "#syspanel")[0].detachservice srv
|
|
|
|
bindContextMenu: (event) ->
|
|
|
|
handler = (e) ->
|
|
|
|
if e.contextmenuHandler
|
|
|
|
e.contextmenuHandler event, ($ "#contextmenu")[0]
|
|
|
|
else
|
|
|
|
p = $(e).parent().get(0)
|
|
|
|
handler p if p isnt ($ "#workspace").get(0)
|
|
|
|
handler event.target
|
|
|
|
event.preventDefault()
|
2017-08-11 01:58:46 +02:00
|
|
|
initDM: ->
|
2017-08-27 23:40:02 +02:00
|
|
|
# check login first
|
2017-08-11 01:58:46 +02:00
|
|
|
_API.resource "schemes/dm.html", (x) ->
|
|
|
|
return null unless x
|
2017-08-15 02:56:04 +02:00
|
|
|
scheme = $.parseHTML x
|
2017-08-11 01:58:46 +02:00
|
|
|
($ "#wrapper").append scheme
|
2018-01-26 18:57:28 +01:00
|
|
|
|
|
|
|
# system menu and dock
|
|
|
|
riot.mount ($ "#syspanel", $ "#wrapper")
|
|
|
|
riot.mount ($ "#sysdock", $ "#wrapper"), { items: [] }
|
|
|
|
|
2017-08-15 02:56:04 +02:00
|
|
|
# context menu
|
|
|
|
riot.mount ($ "#contextmenu")
|
|
|
|
($ "#workspace").contextmenu (e) -> _GUI.bindContextMenu e
|
2018-01-26 18:57:28 +01:00
|
|
|
|
|
|
|
# desktop default file manager
|
|
|
|
desktop = $ "#desktop"
|
|
|
|
desktop[0].fetch = () ->
|
|
|
|
fp = _OS.setting.desktop.path.asFileHandler()
|
|
|
|
fn = () ->
|
|
|
|
fp.read (d) ->
|
|
|
|
return _courrier.osfail d.error, (_API.throwe "OS.VFS"), d.error if d.error
|
|
|
|
items = []
|
|
|
|
$.each d.result, (i, v) ->
|
|
|
|
return if v.filename[0] is '.' and not _OS.setting.desktop.showhidden
|
|
|
|
v.text = v.filename
|
|
|
|
#v.text = v.text.substring(0,9) + "..." ifv.text.length > 10
|
|
|
|
v.iconclass = v.type
|
|
|
|
items.push(v)
|
|
|
|
desktop[0].set "items", items
|
|
|
|
desktop[0].refresh()
|
|
|
|
|
|
|
|
fp.onready () ->
|
|
|
|
fn()
|
|
|
|
, ( e ) -> # try to create the path
|
|
|
|
console.log "#{fp.path} not found"
|
|
|
|
name = fp.basename
|
|
|
|
fp.parent().asFileHandler().mk name, (r) ->
|
|
|
|
ex = _API.throwe "OS.VFS"
|
|
|
|
if r.error then _courrier.osfail d.error, ex, d.error else fn()
|
|
|
|
|
|
|
|
desktop[0].ready = (e) ->
|
|
|
|
e.observable = _courrier
|
|
|
|
window.onresize = () ->
|
|
|
|
_courrier.trigger "desktopresize"
|
|
|
|
e.refresh()
|
|
|
|
|
|
|
|
desktop[0].set "onlistselect", (d) ->
|
|
|
|
($ "#sysdock").get(0).set "selectedApp", null
|
|
|
|
|
|
|
|
desktop[0].set "onlistdbclick", ( d ) ->
|
|
|
|
($ "#sysdock").get(0).set "selectedApp", null
|
|
|
|
it = desktop[0].get "selected"
|
|
|
|
_GUI.openWith it
|
|
|
|
|
2018-01-27 03:16:06 +01:00
|
|
|
#($ "#workingenv").on "click", (e) ->
|
|
|
|
# desktop[0].set "selected", -1
|
2018-01-26 18:57:28 +01:00
|
|
|
|
|
|
|
desktop.on "click", (e) ->
|
2018-01-27 03:16:06 +01:00
|
|
|
return unless e.target is desktop[0]
|
|
|
|
desktop[0].set "selected", -1
|
2018-01-26 18:57:28 +01:00
|
|
|
($ "#sysdock").get(0).set "selectedApp", null
|
|
|
|
console.log "desktop clicked"
|
|
|
|
|
|
|
|
desktop[0].contextmenuHandler = (e, m) ->
|
|
|
|
desktop[0].set "selected", -1 if e.target is desktop[0]
|
2018-01-27 03:16:06 +01:00
|
|
|
($ "#sysdock").get(0).set "selectedApp", null
|
2018-01-26 18:57:28 +01:00
|
|
|
console.log "context menu handler for desktop"
|
|
|
|
|
|
|
|
desktop[0].fetch()
|
|
|
|
_courrier.trigger "desktoploaded"
|
|
|
|
# mount it
|
|
|
|
riot.mount desktop
|
2017-08-27 23:40:02 +02:00
|
|
|
, (e, s) ->
|
|
|
|
alert "System fall: Cannot init desktop manager"
|
2018-01-29 19:16:29 +01:00
|
|
|
console.log s, e
|
|
|
|
|
|
|
|
|
|
|
|
buildSystemMenu: () ->
|
|
|
|
|
|
|
|
menu =
|
|
|
|
text: ""
|
|
|
|
iconclass: "fa fa-eercast"
|
|
|
|
dataid: "sys-menu-root"
|
|
|
|
child: [
|
|
|
|
{
|
|
|
|
text: "Application",
|
|
|
|
child: [],
|
|
|
|
dataid: "sys-apps"
|
|
|
|
iconclass: "fa fa-adn",
|
|
|
|
onmenuselect: (d) ->
|
|
|
|
_GUI.launch d.item.data.app
|
|
|
|
}
|
|
|
|
]
|
|
|
|
menu.child = menu.child.concat _OS.setting.system.menu
|
|
|
|
menu.child.push
|
|
|
|
text: "Log out",
|
|
|
|
dataid: "sys-logout",
|
|
|
|
iconclass: "fa fa-user-times"
|
|
|
|
menu.onmenuselect = (d) ->
|
|
|
|
console.log d
|
|
|
|
return _API.handler.logout() if d.item.data.dataid is "sys-logout"
|
|
|
|
_GUI.launch d.item.data.app unless d.item.data.dataid
|
|
|
|
|
|
|
|
#now get app list
|
|
|
|
_API.packages.fetch (r) ->
|
|
|
|
if r.result
|
|
|
|
v.text = v.name for k, v of r.result
|
|
|
|
menu.child[0].child = r.result if r.result
|
|
|
|
($ "[data-id = 'os_menu']", "#syspanel")[0].set "items", [menu]
|
|
|
|
#console.log menu
|
|
|
|
|
|
|
|
|
2017-08-27 23:40:02 +02:00
|
|
|
login: () ->
|
2018-01-04 11:51:12 +01:00
|
|
|
_OS.cleanup()
|
2017-08-27 23:40:02 +02:00
|
|
|
_API.resource "schemes/login.html", (x) ->
|
|
|
|
return null unless x
|
|
|
|
scheme = $.parseHTML x
|
|
|
|
($ "#wrapper").append scheme
|
|
|
|
($ "#btlogin").click () ->
|
|
|
|
data =
|
|
|
|
username: ($ "#txtuser").val(),
|
|
|
|
password: ($ "#txtpass").val()
|
|
|
|
_API.handler.login data, (d) ->
|
|
|
|
if d.error then ($ "#login_error").html d.error else _GUI.startAntOS d.result
|
|
|
|
, (e, s) ->
|
|
|
|
alert "System fall: Cannot init login screen"
|
|
|
|
|
|
|
|
startAntOS: (conf) ->
|
2018-01-26 18:57:28 +01:00
|
|
|
# clean up things
|
2018-01-04 11:51:12 +01:00
|
|
|
_OS.cleanup()
|
2018-01-26 18:57:28 +01:00
|
|
|
# get setting from conf
|
|
|
|
_OS.setting.desktop = conf.desktop if conf.desktop
|
2017-08-27 23:40:02 +02:00
|
|
|
_OS.setting.applications = conf.applications if conf.applications
|
|
|
|
_OS.setting.appearance = conf.appearance if conf.appearance
|
|
|
|
_OS.setting.user = conf.user
|
2018-01-28 02:01:21 +01:00
|
|
|
_OS.setting.VFS = conf.VFS if conf.VFS
|
2018-01-29 19:16:29 +01:00
|
|
|
_OS.setting.VFS.mountpoints = [
|
|
|
|
#TODO: multi app try to write to this object, it neet to be cloned
|
2018-01-28 02:01:21 +01:00
|
|
|
{ text: "Applications", path: 'app:///', iconclass: "fa fa-adn", type: "app" },
|
|
|
|
{ text: "Home", path: 'home:///', iconclass: "fa fa-home", type: "fs" },
|
|
|
|
{ text: "OS", path: 'os:///', iconclass: "fa fa-inbox", type: "fs" },
|
2018-01-29 19:16:29 +01:00
|
|
|
{ text: "Desktop", path: 'home:///.desktop', iconclass: "fa fa-desktop", type: "fs" },
|
2018-01-28 02:01:21 +01:00
|
|
|
] if not _OS.setting.VFS.mountpoints
|
|
|
|
|
2018-01-29 19:16:29 +01:00
|
|
|
_OS.setting.system = conf.system if conf.system
|
|
|
|
_OS.setting.system.pkgpaths = [
|
|
|
|
"home:///.packages",
|
|
|
|
"os:///packages"
|
|
|
|
] unless _OS.setting.system.pkgpaths
|
|
|
|
_OS.setting.system.menu = [] unless _OS.setting.system.menu
|
2018-01-26 18:57:28 +01:00
|
|
|
_OS.setting.desktop.path = "home:///.desktop" unless _OS.setting.desktop.path
|
2018-01-27 03:16:06 +01:00
|
|
|
_OS.setting.appearance.theme = "antos" unless _OS.setting.appearance.theme
|
2017-08-27 23:40:02 +02:00
|
|
|
# load theme
|
2018-01-27 03:16:06 +01:00
|
|
|
_GUI.loadTheme _OS.setting.appearance.theme
|
2018-01-26 18:57:28 +01:00
|
|
|
# initDM
|
2017-08-27 23:40:02 +02:00
|
|
|
_GUI.initDM()
|
|
|
|
_courrier.observable.one "syspanelloaded", () ->
|
2018-01-26 18:57:28 +01:00
|
|
|
# TODO load packages list then build system menu
|
|
|
|
# push startup services
|
|
|
|
# TODO: get services list from user setting
|
2018-01-29 19:16:29 +01:00
|
|
|
_GUI.buildSystemMenu()
|
|
|
|
_GUI.pushServices [
|
|
|
|
"CoreServices/PushNotification",
|
|
|
|
"CoreServices/Spotlight",
|
|
|
|
"CoreServices/Calendar"
|
|
|
|
]
|
2018-01-26 18:57:28 +01:00
|
|
|
|
|
|
|
# startup application here
|
|
|
|
_courrier.observable.one "desktoploaded", () ->
|
2018-01-28 02:01:21 +01:00
|
|
|
#_GUI.launch "DummyApp"
|
2018-01-29 19:16:29 +01:00
|
|
|
#_GUI.launch "NotePad"
|