From 920d695720602a35dffcc075231a04516a93088f Mon Sep 17 00:00:00 2001 From: Leon van Kammen Date: Tue, 4 Aug 2026 12:17:33 +0200 Subject: [PATCH] updated federation + templates --- src/.init.lua | 2 + src/.lua/config.lua | 17 +----- src/.lua/util.lua | 4 +- src/css/xrforge.css | 4 ++ src/css/xrforge.max.css | 4 +- src/federation.json | 4 -- src/page/about.html | 6 +- src/page/admin/index.html | 3 +- src/page/admin/index.lua | 20 +++++-- src/page/dir.html | 2 +- src/page/dir.lua | 2 +- src/page/footer.html | 2 +- src/page/footer.janusxr.html | 33 ----------- src/page/header.html | 12 ++-- src/page/janusxr.html | 72 +++++++++++++++++++++++ src/plugin/clouddrive.lua | 1 - src/plugin/federation.lua | 109 +++++++++++++++++------------------ src/plugin/git.lua | 1 - src/plugin/global.lua | 62 ++++++++++++++++++++ src/plugin/janusxr.lua | 26 ++++++++- src/plugin/manyfold.lua | 1 - src/plugin/markdown.lua | 1 - src/plugin/moderation.lua | 1 - src/plugin/webhook.lua | 1 - src/plugin/xrfragments.lua | 2 +- 25 files changed, 250 insertions(+), 142 deletions(-) delete mode 100644 src/federation.json delete mode 100644 src/page/footer.janusxr.html create mode 100644 src/page/janusxr.html create mode 100644 src/plugin/global.lua diff --git a/src/.init.lua b/src/.init.lua index 0277a9c..3326091 100644 --- a/src/.init.lua +++ b/src/.init.lua @@ -39,6 +39,7 @@ app = require("soakbean") { end end) end) + app.set('app.opts', app.opts) return p end } @@ -53,6 +54,7 @@ app.init = function() end app.opts = require('config')(app) -- load system plugins (in specific order for admin panel) +app.plugin.global = app.addPlugin('plugin/global') app.plugin.diskscan = app.addPlugin('plugin/diskscan') app.plugin.moderation = app.addPlugin('plugin/moderation') app.plugin.xrfragments = app.addPlugin('plugin/xrfragments') diff --git a/src/.lua/config.lua b/src/.lua/config.lua index e506aec..dffd1e7 100644 --- a/src/.lua/config.lua +++ b/src/.lua/config.lua @@ -5,8 +5,6 @@ return function(app) local config = { -- default name = "XRForge", baseurl="/", - title="your.xr.forge", - subtitle="Portable XR experiences for Phone, VRheadset & desktop.", admin_title = "xrforge admin panel", admin_subtitle = "Manage your XR experiences here", } @@ -30,25 +28,12 @@ return function(app) app.opts = v app.opts.updated = os.time() local newconfig = [[ - -- TIP: run 'xrforge.com createplugin' to start writing plugins -app.on('init', function() - print('config loaded') - - local scan = app.scan - app.scan = function() - os.execute("echo scan before-hook") - scan() - os.execute("echo scan after-hook") - end - -end) - ]] .. "\n\nreturn " .. util.dump(app.opts) newconfig = newconfig:gsub("^}$"," init = function() print('xrforge.lua config loaded') end\n}") util.writefile( app.bindir .. configfile, newconfig ) - print("stored xrforge.lua") + trace("stored xrforge.lua") end end) diff --git a/src/.lua/util.lua b/src/.lua/util.lua index 2aa5831..9393044 100644 --- a/src/.lua/util.lua +++ b/src/.lua/util.lua @@ -97,8 +97,8 @@ util.template = function(content,data) mdata.title = mdata.title or app.opts.subtitle mdata.header_include = mdata.header_include or '' mdata.header = app.tpl( LoadAsset('page/header.html'), mdata ) - if not mdata.footer_janusxr then - mdata.footer_janusxr = app.tpl( LoadAsset('page/footer.janusxr.html'), mdata ) + if not mdata.janusxr then + mdata.janusxr = app.tpl( LoadAsset('page/janusxr.html'), mdata ) end mdata.footer = app.tpl( LoadAsset('page/footer.html'), mdata ) return app.tpl( content, mdata ) diff --git a/src/css/xrforge.css b/src/css/xrforge.css index 608794f..6a57737 100644 --- a/src/css/xrforge.css +++ b/src/css/xrforge.css @@ -51,6 +51,7 @@ td,div,p{ /* form elements */ input, +textarea, select{ box-sizing: border-box; margin: 0px 0px 10px 0px; @@ -69,6 +70,9 @@ input,select,textarea{ input[type=checkbox]{ transform:scale(1.7) translate(3px,4px) } +textarea{ + min-height:150px; +} /* buttons */ diff --git a/src/css/xrforge.max.css b/src/css/xrforge.max.css index fcebdf8..8c38e4c 100644 --- a/src/css/xrforge.max.css +++ b/src/css/xrforge.max.css @@ -54,10 +54,10 @@ body{ font-size:14px; } -.grid .tile img.icon.list-tree{ +img.icon.list-tree{ filter: invert(1); } -.grid .tile img.icon.play{ +img.icon.play{ filter: invert(1); transform: translate(0,-1px); } diff --git a/src/federation.json b/src/federation.json deleted file mode 100644 index 7fb9503..0000000 --- a/src/federation.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - {"url":"https://xrforge.isvery.ninja", "name":"XRForge", "thumbnail":""}, - {"url":"https://www.janusxr.org", "name":"JanusXR", "thumbnail":""} -] diff --git a/src/page/about.html b/src/page/about.html index 3ab7f1a..89e3cba 100644 --- a/src/page/about.html +++ b/src/page/about.html @@ -94,7 +94,7 @@ div#xrecosystem{

What is it

An open, seamless XR web built from simple URLs and directories, without gatekeepers.
- XRForge transforms standard local or remote file directories into interconnected 3D spaces. Users can seamlessly "surf" the spatial web, turning everyday directories into 3D portals. + XRForge transforms standard local or remote file directories into interconnected 3D spaces. Users can seamlessly "surf" spatial webs (plural!), turning everyday directories into 3D portals.

@@ -132,8 +132,8 @@ div#xrecosystem{

Why people want XRForge

- In short: scalable spatial wiki's (it uses web URLs) interconnected via 3D portals; bringing existing 2D ecosystems into XR.
- XRForge interconnects XR experiences via portals, thanks to JanusXR and XR Fragments standards.
+ In short: scalable spatial blog/wiki's (using plain web URLs) interconnected via 3D portals; bringing existing 2D ecosystems into XR.
+ How? Well it's backed by JanusXR- and XR Fragment- URLs.
The metaverse has shown: people like 3D but certain existing 2D ecosystems are king.
They're just more cost-efficient to use.
Hence, XRForge incorporates the opensource JanusXR-client called JanusWeb, which promotes projecting these ecosystems as virtual hyperlinked worlds (via XR translators).
diff --git a/src/page/admin/index.html b/src/page/admin/index.html index 1d2b3c8..90ebc27 100644 --- a/src/page/admin/index.html +++ b/src/page/admin/index.html @@ -8,7 +8,8 @@ ${notification}
{for i,tab in pairs(tabs) do - print('') + if i == 1 then checked='checked' else checked='' end + print('') print('') end} diff --git a/src/page/admin/index.lua b/src/page/admin/index.lua index 761813b..75bfdc9 100644 --- a/src/page/admin/index.lua +++ b/src/page/admin/index.lua @@ -16,7 +16,7 @@ function pluginInput(opt) ]] local key = opt.key:gsub("^app.opts.","") - local value = app.opts[ key ] + local value = EscapeHtml( app.opts[ key ] ) if type(opt.values) == 'table' then html = html .. util.template('\n" else - html = html .. util.template('',{ - key = opt.key, - value = value, - placeholder= opt.placeholder or '' - }) + if opt.control and opt.control == 'textarea' then + html = html .. util.template('',{ + key = opt.key, + value = value, + placeholder= opt.placeholder or '' + }) + else + html = html .. util.template('',{ + key = opt.key, + value = value, + placeholder= opt.placeholder or '' + }) + end end html = html .. util.template([[ diff --git a/src/page/dir.html b/src/page/dir.html index 5cd5759..612994c 100644 --- a/src/page/dir.html +++ b/src/page/dir.html @@ -5,7 +5,7 @@ ${header}

${opts.title}


-
${opts.subtitle}
+
${opts.plugin_global_subtitle}

]]) diff --git a/src/page/dir.lua b/src/page/dir.lua index d4eec15..052e417 100644 --- a/src/page/dir.lua +++ b/src/page/dir.lua @@ -66,7 +66,7 @@ return { data.url = GetScheme() .. '://' .. GetHost() .. port .. v.url if v.janusxr then -- what to do here? no generated portals? - data.footer_janusxr = app.tpl( util.readfile(v.path), data ) + data.janusxr = app.tpl( util.readfile(v.path), data ) end end end) diff --git a/src/page/footer.html b/src/page/footer.html index d515275..6ff05ad 100644 --- a/src/page/footer.html +++ b/src/page/footer.html @@ -38,7 +38,7 @@ -${footer_janusxr} +${janusxr} - ${opts.plugin_diskscan_dirname} about - + ${opts.plugin_global_topmenu_mapname}  + {if true then + print( app.opts.plugin_global_topmenu_html:gsub("\n"," ") ) + end} diff --git a/src/page/janusxr.html b/src/page/janusxr.html new file mode 100644 index 0000000..7fc8d86 --- /dev/null +++ b/src/page/janusxr.html @@ -0,0 +1,72 @@ + + + + {if items and #items > 0 then + for i,v in pairs(items) do + print('\t') + end + end} + {for i=1,5 do + local urls = app.opts[ 'plugin_federation_url_' .. i] + if #urls > 0 then + local fediurl = urls:gsub(' .*','') + local thumburl = urls:gsub('.* ','') + print('\t') + end + end} + + {if item then + print([[ + + + ]]) + else + local room = app.opts.plugin_janusxr_portalroom + if room == 'random' then room = app.plugin.janusxr.getRandomRoom() end + print('') + end} + + {if true then + function addPortal(id,x,v,url,i,z,thumbprefix,rotation,scale) + print('\t\t') + print('\t\t ') + print('\t\t ') + print('\t\t ') + print('\t\t') + end + end} + + {if items and #items > 0 then + local portals = {} + for i,v in pairs(items) do table.insert(portals, v) end + if parent then table.insert(portals, p) end + for i,v in pairs(items) do + local width = 3.2 + local center = -((#items*width)/1.3) + (i*width) + local url = v.url + if v.dir then url = url .. "/" end + addPortal('dir',center, v, url,i, -4, 'img', '0 0 0', '0.2 0.2 0.2') + end + end} + {if true then + local portals = {} + for i=1,5 do + local urls = app.opts[ 'plugin_federation_url_' .. i] + if #urls > 0 then + local fediurl = urls:gsub(' .*','') + table.insert(portals, fediurl ) + end + end + if #portals > 0 then + print([[ + + ]]) + end + for i,fediurl in pairs(portals) do + local width = 3.2 + local center = -((#portals*width)/1.3) + (i*width) + addPortal('federated',center, {title=fediurl}, fediurl,i, 4, 'federated', '0 180 0', '0.1 0.1 0.1') + end + end} + + diff --git a/src/plugin/clouddrive.lua b/src/plugin/clouddrive.lua index fdd7857..985591e 100644 --- a/src/plugin/clouddrive.lua +++ b/src/plugin/clouddrive.lua @@ -9,7 +9,6 @@ app.on('scan_experience_file', function(exp) end) app.on('set', function(k,v) - print("content was updated") end) -- this registers the plugin UI diff --git a/src/plugin/federation.lua b/src/plugin/federation.lua index 7971936..5105495 100644 --- a/src/plugin/federation.lua +++ b/src/plugin/federation.lua @@ -8,83 +8,78 @@ app.on('scan_experience_file', function(exp) end) app.on('set', function(k,v) - print("content was updated") end) ---app.on('dir', function(opts) --- local me = app.plugin.federation --- if opts.urlpath == '/' then --- foreach( me.portals, function(k,portal) --- print("JAAA") --- table.insert( opts.data.items,{ --- url = portal.url, --- name = portal.name, --- thumbnail = portal.thumbnail --- }) --- end) --- end ---end) +app.on('dir', function(opts) + local me = app.plugin.federation + if opts.urlpath == '/' then + print_r(me.portals) + --foreach( me.portals, function(k,portal) + -- print("JAAA") + -- table.insert( opts.data.items,{ + -- url = portal.url, + -- name = portal.name, + -- thumbnail = portal.thumbnail + -- }) + --end) + end +end) local plugin = { - name = 'Federation disabled', - info = 'updating values requires a xrforge restart', + name = 'Federation', + info = 'Add links to other (janus)XR(forges), and have them show up as extra portals in portalrooms', opts = { -- TODO populate this based on xrforge-federation.json + { + key='app.opts.plugin_federation_title', + title='Title', + info="Displayed above federated portals", + default="Federated neighbourhoods", + values='' + }, + { + key='app.opts.plugin_federation_strategy', + title='Display portals', + info="When to show federated portals?", + default="always", + values={always='always',homepage='only homepage'} + }, { key='app.opts.plugin_federation_url_1', - title='Federation URL 1', - info="a json with (janus)xr(forge) URLs", - default="./federation.json", + title='Federated URL 1', + info="URL + Thumbnail URL (space separated)", + default="https://xrforge.isvery.ninja https://i.imgur.com/x7fzn9v.png", values='' }, { key='app.opts.plugin_federation_url_2', - title='Federation URL 1', - info="a json with (janus)xr(forge) URLs", - default="", + title='Federated URL 2', + info="URL + Thumbnail URL (space separated)", + default="https://www.janusxr.org/new/ https://archive.org/download/janusxr-1/janusxr.png", values='' }, { key='app.opts.plugin_federation_url_3', - title='Federation URL 1', - info="a json with (janus)xr(forge) URLs", + title='Federated URL 3', + info="URL + Thumbnail URL (space separated)", + default="", + values='' + }, + { + key='app.opts.plugin_federation_url_4', + title='Federated URL 4', + info="URL + Thumbnail URL (space separated)", + default="", + values='' + }, + { + key='app.opts.plugin_federation_url_5', + title='Federated URL 5', + info="URL + Thumbnail URL (space separated)", default="", values='' } } } --- --- PROBLEM: every request has its own app context --- so the util.fetch() didn't help here --- sqlite is needed to share state - -app.on('init', function() - local me = app.plugin.federation - me.portals = {} - local federations = {} - -- load previous federations if any - for k=1,3 do - if app.opts['plugin_federation_url_'..k] and #app.opts['plugin_federation_url_'..k] > 0 then - table.insert(federations, app.opts['plugin_federation_url_'..k]) - end - end - - foreach(federations, function(k,url) - if url:match('^[./]') then - url = util.getURL( url:gsub('^[./]',''), {server=true} ) - end - util.fetch(url, nil, function(req,res,next) - if req.body then - local t = DecodeJson(req.body) - if t then - foreach( t, function(k,opt) - table.insert( me.portals, opts ) - end) - end - end - end) - end) -end) - -- this registers the plugin UI return plugin diff --git a/src/plugin/git.lua b/src/plugin/git.lua index 764329e..c5217eb 100644 --- a/src/plugin/git.lua +++ b/src/plugin/git.lua @@ -8,7 +8,6 @@ app.on('scan_experience_file', function(exp) end) app.on('set', function(k,v) - print("content was updated") end) -- this registers the plugin UI diff --git a/src/plugin/global.lua b/src/plugin/global.lua new file mode 100644 index 0000000..816bed9 --- /dev/null +++ b/src/plugin/global.lua @@ -0,0 +1,62 @@ +local util = require('util') + +app.on('scan_experience', function(exp) + --print_r(exp) +end) + +app.on('scan_experience_file', function(exp) +end) + +app.on('set', function(k,v) +end) + +-- this registers the plugin UI +local plugin = { + name = "Global settings", + info = '', + opts = { + { + key='app.opts.plugin_global_title', + title='Title', + info='Preferably dot-style domain-notation for easy recollection', + default = "your.xr.forge", + values='' + }, + { + key='app.opts.plugin_global_subtitle', + title='Subtitle', + info='Slogan here', + default = "Portable XR experiences for Phone, VRheadset & desktop.", + values='' + }, + { + key='app.opts.plugin_global_topmenu_mapname', + title='Overview link', + info='Top-right link (overview page)', + default = "map", + values='' + }, + { + key='app.opts.plugin_global_topmenu_html', + title='Menu html', + info='Add extra menu items here', + default = 'about', + control='textarea', + values='' + }, + { + key='app.opts.plugin_global_headertags', + title='Header html', + info='Add extra header tags here', + default = [[ + + ]], + control='textarea', + values='' + }, + } +} + +return plugin diff --git a/src/plugin/janusxr.lua b/src/plugin/janusxr.lua index 1601a48..82baffe 100644 --- a/src/plugin/janusxr.lua +++ b/src/plugin/janusxr.lua @@ -31,7 +31,6 @@ app.on('scan_experience_file', function(exp) end) app.on('set', function(k,v) - print("content was updated") end) -- this registers the plugin UI @@ -76,11 +75,18 @@ local plugin = { }, { key='app.opts.plugin_janusxr_wrap_template', - title='template', + title='Media room', info='What kind of space should images/videos be rendered into?', default="random", values={random="random room",plane="wirefloor",room1="room1",room2="room2",room3="room3",room4="room4",room5="room5",room6="room6",room7="room7"} }, + { + key='app.opts.plugin_janusxr_portalroom', + title='Directory room', + info='What kind of space should directories be rendered into?', + default="room_plane", + values={random="random room",room_plane="wirefloor",room1="room1",room2="room2",room3="room3",room4="room4",room5="room5",room6="room6",room7="room7"} + }, { key='app.opts.plugin_janusxr_scraper', title='Scraper', @@ -95,7 +101,21 @@ local plugin = { default='https://xrforge.isvery.ninja https://www.janusxr.org', values='' }, - } + }, + getRandomRoom = function() + local me = app.plugin.janusxr + local room= '' + foreach( me.opts, function(k,v) + print(v.key) + if v.key == 'app.opts.plugin_janusxr_portalroom' then + local ordered = {} + foreach( v.values, function(k,v) table.insert(ordered,v) end) + room = ordered[ math.random( #ordered ) ] + end + end) + print("ROOM = " .. room) + return room + end } return plugin diff --git a/src/plugin/manyfold.lua b/src/plugin/manyfold.lua index 1a6db73..481a06c 100644 --- a/src/plugin/manyfold.lua +++ b/src/plugin/manyfold.lua @@ -8,7 +8,6 @@ app.on('scan_experience_file', function(exp) end) app.on('set', function(k,v) - print("content was updated") end) -- this registers the plugin UI diff --git a/src/plugin/markdown.lua b/src/plugin/markdown.lua index d7af64a..7e19bd0 100644 --- a/src/plugin/markdown.lua +++ b/src/plugin/markdown.lua @@ -17,7 +17,6 @@ app.on('scan_experience_file', function(exp) end) app.on('set', function(k,v) - print("content was updated") end) -- this registers the plugin UI diff --git a/src/plugin/moderation.lua b/src/plugin/moderation.lua index 087541a..e71a727 100644 --- a/src/plugin/moderation.lua +++ b/src/plugin/moderation.lua @@ -8,7 +8,6 @@ app.on('scan_experience_file', function(exp) end) app.on('set', function(k,v) - print("content was updated") end) -- this registers the plugin UI diff --git a/src/plugin/webhook.lua b/src/plugin/webhook.lua index 27616aa..83f693c 100644 --- a/src/plugin/webhook.lua +++ b/src/plugin/webhook.lua @@ -8,7 +8,6 @@ app.on('scan_experience_file', function(exp) end) app.on('set', function(k,v) - print("content was updated") end) -- this registers the plugin UI diff --git a/src/plugin/xrfragments.lua b/src/plugin/xrfragments.lua index 93b4dd0..8db0f51 100644 --- a/src/plugin/xrfragments.lua +++ b/src/plugin/xrfragments.lua @@ -49,7 +49,7 @@ end) -- this registers the plugin UI /funcs return { name = "XR Fragments", - info = 'XR Fragments treats 3D files with sidecar file(s) (foo.glb+foo.png e.g.) as experience and/or detect deeplinking of 3D files via href-metadata', + info = 'XR Fragments treats 3D files with sidecar file(s) (foo.glb+foo.png e.g.) as experience and/or detects deeplinking of 3D files via href-metadata', opts = { { key='app.opts.plugin_xrfragments_filetypes',