+ ]])
+ end
+ print(' ')
+ end
+ end}
+
${opts}
diff --git a/src/page/dir.lua b/src/page/dir.lua
index 87eb25a..6b21820 100644
--- a/src/page/dir.lua
+++ b/src/page/dir.lua
@@ -99,7 +99,6 @@ return {
-- what to do here? no generated portals?
data.janusxr = app.tpl( util.readfile(v.path), data )
end
- print_r(data.item)
end
end
end)
diff --git a/src/plugin/diskscan.lua b/src/plugin/diskscan.lua
index 113632b..6e68dba 100644
--- a/src/plugin/diskscan.lua
+++ b/src/plugin/diskscan.lua
@@ -43,7 +43,6 @@ return {
end,
scan = function(scandir)
- app.reset() -- flush cache
local me = app.plugin.diskscan
local seen = {symlinks={}}
-- ensure rootdir as experience
diff --git a/src/plugin/global.lua b/src/plugin/global.lua
index 8439721..4415588 100644
--- a/src/plugin/global.lua
+++ b/src/plugin/global.lua
@@ -98,51 +98,60 @@ local plugin = {
title='Viewer instructions',
info='Default popup for 3D viewer instructions',
default = [[
-
Tips to navigate in XR
-
-
-
- AR/VR headset
-
-
- walk around / use right-longpinch (or thumbstick) for local teleports
-
-
-
-
- PhoneVR
-
-
- use gaze or bluetooth/mouse to navigate
-
-
-
-
- PhoneAR
-
-
- walk around and tap screen to click
-
-
-
-
- Mobile
-
-
- use the WASD-keys and mousedrag to navigate
-
-
-
-
- Keyboard+Mouse
-
-
- use the WASD-keys and mousedrag to navigate
-
-
-
+
Hi there! đ
+Welcome to this XR experience.
+
+
+
+
+
+
+
+
+
+
+ AR/VR headset
+
+
+ walk around / use right-longpinch (or thumbstick) for local teleports
+
+
+
+
+ PhoneVR
+
+
+ use gaze or bluetooth/mouse to navigate
+
+
+
+
+ PhoneAR
+
+
+ walk around and tap screen to click
+
+
+
+
+ Mobile
+
+
+ use the WASD-keys and mousedrag to navigate
+
+
+
+
+ Keyboard+Mouse
+
+
+ use the WASD-keys and mousedrag to navigate
+
+
+
You've got this!
+
]],
control='textarea',
diff --git a/src/plugin/janusxr/layout/grid.lua b/src/plugin/janusxr/layout/grid.lua
index 68cb450..617b124 100644
--- a/src/plugin/janusxr/layout/grid.lua
+++ b/src/plugin/janusxr/layout/grid.lua
@@ -27,11 +27,12 @@ local grid = {
local index = 0
for i, v in pairs(items) do
local url = v.redirect and v.redirect or v.url
+ local overlay = v.title:match('#overlay') and true or false
-- Position current item
local pos = {
- x = v.title:match("#overlay") and 0 or x * gridsize,
+ x = overlay and 0 or x * gridsize,
y = 0,
- z = v.title:match("#overlay") and 0 or z * gridsize
+ z = overlay and 0 or z * gridsize
}
local posStr = pos.x .. ' ' .. pos.y .. ' ' .. pos.z
local is_nested_room = false
@@ -41,24 +42,26 @@ local grid = {
else
jml = jml .. ' \n'
end
- index = index + 1
- -- Move to next position in the spiral
- if index < #items then
- x = x + dx
- z = z + dz
- stepsTaken = stepsTaken + 1
- if stepsTaken == steps then
- stepsTaken = 0
- -- Rotate clockwise: right -> up -> left -> down
- local oldDx = dx
- dx = -dz
- dz = oldDx
- turns = turns + 1
- -- Increase the length after every second turn
- if turns % 2 == 0 then
- steps = steps + 1
- end
- end
+ if not overlay then
+ index = index + 1
+ -- Move to next position in the spiral
+ if index < #items then
+ x = x + dx
+ z = z + dz
+ stepsTaken = stepsTaken + 1
+ if stepsTaken == steps then
+ stepsTaken = 0
+ -- Rotate clockwise: right -> up -> left -> down
+ local oldDx = dx
+ dx = -dz
+ dz = oldDx
+ turns = turns + 1
+ -- Increase the length after every second turn
+ if turns % 2 == 0 then
+ steps = steps + 1
+ end
+ end
+ end
end
end
return jml
diff --git a/src/plugin/manyfold.lua b/src/plugin/manyfold.lua
index 625b2de..17faa8b 100644
--- a/src/plugin/manyfold.lua
+++ b/src/plugin/manyfold.lua
@@ -1,64 +1,312 @@
-local util = require('util')
+local util = require('util')
+local apiSync = require('apiSync')
-app.on('scan_experience', function(exp)
- --print_r(exp)
-end)
+--app.on('init', function()
+-- app.plugin.manyfold.api = apiSync.init( 'manyfold' )
+--end)
-app.on('scan_experience_file', function(exp)
-end)
+local function scanTiltFile(exp)
+ if exp.path:lower():match(".tilt$") then
+ app.markViewable(exp)
+ end
+end
+
+local function scanForOpenBrush(exp)
+ local tags = app.plugin.manyfold.tags
+ if not tags then
+ tags = util.split( app.opts.plugin_manyfold_sync_hashtag, ' ')
+ table.insert( tags,"manyfold")
+ app.plugin.manyfold.tags = tags
+ end
+ foreach( tags, function(k,tag)
+ tag = tag:gsub("#","")
+ if exp.path:match('/' .. tag .. '/') then -- might not be precise enough
+ if not exp.parent.janusxr then
+ exp.parent.janusxr = {}
+ end
+ exp.parent.janusxr.room = app.opts.plugin_manyfold_wrap_room
+ exp.parent.portal_width = tonumber( app.opts.plugin_manyfold_portal_width )
+ exp.parent.layout = app.opts.plugin_manyfold_layout
+ end
+ end)
+ scanTiltFile(exp)
+end
+
+
+--app.on('scan_experience', scanForOpenBrush )
+--app.on('scan_experience_file', scanForOpenBrush )
+--app.on("scan_experience_janusxr", function(opts) scanForOpenBrush(opts.exp) end)
app.on('set', function(k,v)
end)
+local sync_URL = app.opts_plugin_manyfold_sync_URL or ''
+
-- this registers the plugin UI
local plugin = {
- name = "Manyfold",
- tab = " Manyfold",
- info = '',
+ name = "ManyFold",
+ infowide = true,
+ info = [[
+
+ OpenBrush lets you paint in 3D space with virtual reality.
+ XRForge's webviewer (JanusWeb) supports interconnecting OpenBrush projects via 3D portals or a grid.
+ OpenBrush projects are stored in a (selfhosted) icosa.gallery instance, which can be configured below.
+ NOTE: for collective virtualworld building use hashtags in project-titles. Each hashtag will become its own folder, which allows for crowdsourcing/combining scenes designed in manyfold.
+ ]],
+ --buttons = {
+ -- { label = "resync now!", href="/reset" }
+ --},
opts = {
{
- key='app.opts.plugin_manyfold_instance_1',
- title='Instance 1 URL',
- info='Manyfold URL goes here (https://xrforge.isvery.ninja e.g.)',
- default="https://xrforge.isvery.ninja",
- values=''
+ key='app.opts.plugin_manyfold_wrap_room',
+ title='Wrap VR space',
+ info='render 3D files in janusxr.xml room',
+ default="room_plane",
+ values= app.plugin.janusxr.opts[4].values -- reuse rooms from janusxr plugin
},
{
- key='app.opts.plugin_manyfold_instance_2',
- title='Instance 2 URL',
- info='Manyfold URL goes here (https://xrforge.isvery.ninja e.g.)',
- default="",
- values=''
+ key='app.opts.plugin_manyfold_layout',
+ title='Layout assets',
+ info='NOTE: use #overlay in asset-title to skip layout (sky/floor/e.g.)',
+ default="grid",
+ values={portals="As portals", grid="As grid"}
},
{
- key='app.opts.plugin_manyfold_instance_3',
- title='Instance 3 URL',
- info='Manyfold URL goes here (https://xrforge.isvery.ninja e.g.)',
- default="",
+ key='app.opts.plugin_manyfold_layout_grid_size',
+ title='Grid size',
+ info='in square meters (only used for grid layout)',
+ default="3",
+ placeholder="3",
values=''
},
{
key='app.opts.plugin_manyfold_sync_strategy',
- title='Sync strategy',
- info="Specify how content from manyfold instances should be fetched",
- default="recent",
- values={recent='only recent',all_recent='everything + recent', disabled='disabled'}
+ title='How to sync',
+ info='download assets locally (prevent linkrot)',
+ default = "mirror",
+ values={mirror="mirror locally"}
},
- --{
- -- key='app.opts.plugin_manyfold_sync_strategy',
- -- title='Instance 3 URL',
- -- info='Specify how content from manyfold instances should be fetched",
- -- default="recent",
- -- values={recent='only recent',all_recent='everything + recent', disabled='disabled'}
- --},
- --{
- -- key='app.opts.plugin_manyfold_sync_interval',
- -- title='Instance 3 URL',
- -- info='Specify how often xrforge should check for recent items #serveronly'
- -- default="recent",
- -- values={recent='only recent',all_recent='everything + recent', disabled='disabled'}
- --},
- }
+ {
+ key='app.opts.plugin_manyfold_sync_when',
+ title='Sync interval',
+ info='when to sync?',
+ default = "boot",
+ values={disabled="disabled", boot="on boot", hourly="hourly", daily="daily"}
+ },
+ {
+ key='app.opts.plugin_manyfold_sync_folder',
+ title='Sync to folder',
+ info='manyfold (icosa.gallery) assets will be saved here',
+ placeholder = "manyfold",
+ default = app.opts.plugin_diskscan_dir,
+ values = {}
+ },
+ {
+ key='app.opts.plugin_manyfold_sync_folder_thumbnail',
+ title='Thumbnail',
+ info='URL of Thumbnail for folder/portal',
+ placeholder = "img/manyfold.png",
+ default = "img/manyfold.png",
+ values=''
+ },
+ {
+ key='app.opts.plugin_manyfold_portal_width',
+ title='Portal spacing',
+ info='Spacing between portals (prevent thumbnail-overlap)',
+ placeholder = "4.2",
+ default = "4.2",
+ values=''
+ },
+ {
+ key='app.opts.plugin_manyfold_sync_URL',
+ title='Icosa gallery URL',
+ info='public/selfhosted icosa.gallery server-instance',
+ placeholder = "icosa.gallery",
+ default = "icosa.gallery",
+ values=''
+ },
+ {
+ key='app.opts.plugin_manyfold_sync_hashtag',
+ title='tags',
+ info=( sync_URL and 'space-separated tags will generate their own folders' or ''),
+ default = "#1 #xrforge",
+ placeholder = "#1 #xrforge",
+ values=''
+ },
+ {
+ key='app.opts.plugin_manyfold_sync_category',
+ title='category',
+ info=( sync_URL and 'space-separated, leave empty or see API docs' or ''),
+ placeholder = "ART",
+ default = "",
+ values=''
+ },
+ {
+ key='app.opts.plugin_manyfold_sync_keywords',
+ title='keywords',
+ info=( sync_URL and 'space-separated, leave empty or see API docs' or ''),
+ placeholder = "xrforge",
+ default = "",
+ values=''
+ },
+ {
+ key='app.opts.plugin_manyfold_sync_triangle_max',
+ title='Polygons maximum',
+ info=( sync_URL and 'performance-cap, leave empty or see API docs' or ''),
+ placeholder = "10000",
+ default = "",
+ values=''
+ },
+ {
+ key='app.opts.plugin_manyfold_sync_license',
+ title='License',
+ info='filter assets on specific license',
+ default = "",
+ values={ [""]="", ALL_CC="CreateCommons (ALL)"}
+ },
+ {
+ key='app.opts.plugin_manyfold_sync_author',
+ title='Author name',
+ info='space-separated: filter assets on specific Author name',
+ placeholder='sarah',
+ default = "",
+ values=""
+ },
+ {
+ key='app.opts.plugin_manyfold_sync_authorid',
+ title='Author id',
+ info='space-separated: filter assets on specific Author id',
+ placeholder='9e8b98fbe',
+ default = "",
+ values=""
+ },
+ {
+ key='app.opts.plugin_manyfold_sync_maxitems',
+ title='Max latest items',
+ info='limit the total amount of result',
+ placeholder='3',
+ default = "3",
+ values=""
+ },
+ {
+ key='app.opts.plugin_manyfold_sync_collection',
+ title='In collection',
+ info='should assets be part of a collection?',
+ default = "disabled",
+ values={enabled="yes", disabled="no"}
+ }
+ },
+
+ -- expected by src/.lua/apiSync.lua
+ apiCall = function(tag)
+ return 'https://api.' .. app.opts.plugin_manyfold_sync_URL .. '/v1/assets?xrforge=' .. EscapeFragment(app.host)
+ .. '&xrforge_strategy=' .. EscapeFragment(app.opts.plugin_manyfold_sync_strategy)
+ .. '&time=' .. tostring( os.time() )
+ .. (tag and #tag > 0 and '&keywords=' .. EscapeFragment(tag) or '')
+ .. (#app.opts.plugin_manyfold_sync_category > 0 and '&category=' .. EscapeFragment(app.opts.plugin_manyfold_sync_category) or '')
+ .. (#app.opts.plugin_manyfold_sync_keywords > 0 and '&keywords=' .. EscapeFragment(app.opts.plugin_manyfold_sync_keywords) or '')
+ .. (#app.opts.plugin_manyfold_sync_triangle_max > 0 and '&triangleCountMax=' .. EscapeFragment(app.opts.plugin_manyfold_sync_triangle_max) or '')
+ .. (#app.opts.plugin_manyfold_sync_license > 0 and '&license=' .. app.opts.plugin_manyfold_sync_license or '' )
+ .. (app.opts.plugin_manyfold_sync_collection == 'enabled' and '&inCollection=true' or '' )
+ .. (#app.opts.plugin_manyfold_sync_maxitems > 0 and '&pageSize=' .. EscapeFragment(app.opts.plugin_manyfold_sync_maxitems) or '' )
+ -- TODO: filter AFTER the request
+ -- .. (#app.opts.plugin_manyfold_sync_author > 0 and '&authorName=' .. EscapeFragment(app.opts.plugin_manyfold_sync_author) or '')
+ -- .. (#app.opts.plugin_manyfold_sync_authorid > 0 and '&authorId=' .. EscapeFragment(app.opts.plugin_manyfold_sync_authorid) or '')
+ end,
+
+ getFolder = function(tag)
+ local folder = app.opts.plugin_manyfold_sync_folder
+ if tag then
+ folder = folder .. '/' .. util.hyphenate(tag)
+ end
+ return folder
+ end,
+
+ -- expected by src/.lua/apiSync.lua
+ fetch = function(url,opts)
+ opts = opts or {}
+ if not opts.body then
+ local ok, headers, body = Fetch( url )
+ if not ok then
+ return print("[manyfold.lua] error: could not fetch: " .. app.plugin.manyfold.apiCall(tag))
+ end
+ opts.body = body
+ end
+ return DecodeJson(opts.body)
+ end,
+
+ -- expected by src/.lua/apiSync.lua
+ download = function(t,tag)
+ local me = app.plugin.manyfold
+ local synced = 0
+ foreach( t.assets, function(k,asset)
+ if type(asset) == 'table' then
+ local dirname = '_' .. asset.assetId .. '-' .. util.hyphenate( asset.displayName)
+ local dirnameFull = me.getFolder(tag) .. '/' .. dirname
+ local jsonfile = dirnameFull .. '/asset.json'
+ local sync = true
+ local assetPrevious = false
+ local f = false
+
+ function preferFormat(f)
+ local found = false
+ foreach( asset.formats, function(k,v)
+ if v.formatType == f then
+ found = v
+ end
+ end)
+ return found
+ end
+
+ f = preferFormat('TILT')
+ if not f then f = preferFormat('GLTF2') end
+ if not f then f = preferFormat('GLTF1') end
+ if not f then f = preferFormat('OBJ') end
+ if f then
+ if not util.fileExist( dirnameFull ) then
+ os.execute("mkdir -p " .. dirnameFull)
+ end
+
+ if util.fileExist(jsonfile) then
+ assetPrevious = DecodeJson( util.readfile(jsonfile) )
+ if util.parseIsoDate(asset.updateTime) == util.parseIsoDate(assetPrevious.updateTime) then
+ sync = false -- already finished
+ end
+ end
+ if sync then
+ print('â ' .. asset.displayName .. ' (syncing) #manyfold')
+ util.writefile( jsonfile, EncodeJson(asset) )
+ local rootfile = dirnameFull .. '/' .. f.root.url:gsub(".*/","")
+ local thumbnailfile = ''
+ if asset.thumbnail then
+ thumbnailfile = dirnameFull .. '.' .. asset.thumbnail.url:gsub(".*%.",'')
+ print('đ¤ fetch ' .. asset.thumbnail.url)
+ os.execute('wget "' ..asset.thumbnail.url .. '" -O "' .. thumbnailfile .. '"')
+ end
+ print('đ¤ fetch ' .. f.root.url)
+ os.execute('wget "' .. f.root.url .. '" -O "' .. rootfile .. '"')
+ if #f.resources > 0 then
+ foreach( f.resources, function(k,resource)
+ local file = dirnameFull .. '/' .. resource.url:gsub(".*/","")
+ print('đ¤ fetch ' .. resource.url)
+ os.execute('wget "' .. resource.url .. '" -O "' .. file .. '"')
+ end)
+ end
+ synced = synced + 1
+ else
+ print('âšī¸ ' .. asset.displayName .. ' (up to date) #manyfold')
+ end
+ else
+ print('[manyfold.lua] error: no suitable format found for ' .. asset.displayName .. ' ' .. asset.assetId)
+ end
+ end
+ end, true)
+ return synced
+ end
}
+if not util.cmdExist('wget') then
+ plugin.info = plugin.info .. '
NOTE: wget command not installed..plugin is disabled'
+end
+
return plugin
diff --git a/src/plugin/openbrush.lua b/src/plugin/openbrush.lua
index 1ce884c..0c31b8f 100644
--- a/src/plugin/openbrush.lua
+++ b/src/plugin/openbrush.lua
@@ -1,34 +1,8 @@
-local util = require('util')
+local util = require('util')
local apiSync = require('apiSync')
-local syncIcosaGallery = function()
- if #app.opts.plugin_openbrush_sync_URL > 0 then
- local synced = apiSync.syncHashtags({
- tags = util.split( app.opts.plugin_openbrush_sync_hashtag or '', ' '),
- apiCall = app.plugin.openbrush.apiCall,
- fetch = app.plugin.openbrush.fetch,
- download = app.plugin.openbrush.download
- })
- end
-end
-
app.on('init', function()
- foreach( app.plugin.openbrush.opts, function(k,opt)
- if opt.key == 'app.opts.plugin_openbrush_sync_folder' then
- opt.values = app.cache.dirs
- end
- end)
- if util.contains(argv, 'generate') then
- syncIcosaGallery()
- end
-end)
-
-app.on('scheduler', function(opts)
- if util.contains(argv, 'server') then
- if util.cmdExist('wget') and opts.interval == app.opts.plugin_openbrush_sync_when then
- syncIcosaGallery()
- end
- end
+ app.plugin.openbrush.api = apiSync.init( 'openbrush' )
end)
local function scanTiltFile(exp)
@@ -52,6 +26,7 @@ local function scanForOpenBrush(exp)
end
exp.parent.janusxr.room = app.opts.plugin_openbrush_wrap_room
exp.parent.portal_width = tonumber( app.opts.plugin_openbrush_portal_width )
+ exp.parent.grid_size = tonumber( app.opts.plugin_openbrush_grid_size )
exp.parent.layout = app.opts.plugin_openbrush_layout
end
end)
@@ -75,39 +50,42 @@ local plugin = {
info = [[
OpenBrush lets you paint in 3D space with virtual reality.
- XRForge's webviewer (JanusWeb) supports interconnecting OpenBrush projects via 3D portals.
+ XRForge's webviewer (JanusWeb) supports interconnecting OpenBrush projects via 3D portals or a grid.
OpenBrush projects are stored in a (selfhosted) icosa.gallery instance, which can be configured below.
NOTE: for collective virtualworld building use hashtags in project-titles. Each hashtag will become its own folder, which allows for crowdsourcing/combining scenes designed in openbrush.
]],
+ --buttons = {
+ -- { label = "resync now!", href="/reset" }
+ --},
opts = {
{
key='app.opts.plugin_openbrush_wrap_room',
title='Wrap VR space',
info='render 3D files in janusxr.xml room',
- default="room_plane",
+ default="",
values= app.plugin.janusxr.opts[4].values -- reuse rooms from janusxr plugin
},
{
key='app.opts.plugin_openbrush_layout',
title='Layout assets',
info='NOTE: use #overlay in asset-title to skip layout (sky/floor/e.g.)',
- default="portals",
+ default="grid",
values={portals="As portals", grid="As grid"}
},
{
key='app.opts.plugin_openbrush_layout_grid_size',
title='Grid size',
- info='in square meters (unused for non-grid layout)',
- default="3",
- placeholder="3",
+ info='in square meters (only used for grid layout)',
+ default="75",
+ placeholder="75",
values=''
},
{
key='app.opts.plugin_openbrush_sync_strategy',
title='How to sync',
- info='mirroring = most resilient; references = instant updates',
+ info='download assets locally (prevent linkrot)',
default = "mirror",
- values={mirror="mirror locally",reference="reference remote URL"}
+ values={mirror="mirror locally"}
},
{
key='app.opts.plugin_openbrush_sync_when',
@@ -116,13 +94,6 @@ local plugin = {
default = "boot",
values={disabled="disabled", boot="on boot", hourly="hourly", daily="daily"}
},
- {
- key='app.opts.plugin_openbrush_sync_bruteforce',
- title='Sync anyways',
- info='ignore timestamps',
- default = "enabled",
- values={disabled="disabled", enabled="enabled"}
- },
{
key='app.opts.plugin_openbrush_sync_folder',
title='Sync to folder',
@@ -142,7 +113,7 @@ local plugin = {
{
key='app.opts.plugin_openbrush_portal_width',
title='Portal spacing',
- info='Adjust spacing between portals (prevent thumbnail-overlap)',
+ info='Spacing between portals (prevent thumbnail-overlap)',
placeholder = "4.2",
default = "4.2",
values=''
@@ -159,8 +130,8 @@ local plugin = {
key='app.opts.plugin_openbrush_sync_hashtag',
title='tags',
info=( sync_URL and 'space-separated tags will generate their own folders' or ''),
- default = "#1 #xrforge",
- placeholder = "#1 #xrforge",
+ default = "#xrforge",
+ placeholder = "#xrforge",
values=''
},
{
@@ -187,6 +158,13 @@ local plugin = {
default = "",
values=''
},
+ {
+ key='app.opts.plugin_openbrush_sync_license',
+ title='License',
+ info='filter assets on specific license',
+ default = "",
+ values={ [""]="", ALL_CC="CreateCommons (ALL)"}
+ },
{
key='app.opts.plugin_openbrush_sync_author',
title='Author name',
@@ -220,14 +198,16 @@ local plugin = {
}
},
+ -- expected by src/.lua/apiSync.lua
apiCall = function(tag)
return 'https://api.' .. app.opts.plugin_openbrush_sync_URL .. '/v1/assets?xrforge=' .. EscapeFragment(app.host)
.. '&xrforge_strategy=' .. EscapeFragment(app.opts.plugin_openbrush_sync_strategy)
+ .. '&time=' .. tostring( os.time() )
.. (tag and #tag > 0 and '&keywords=' .. EscapeFragment(tag) or '')
.. (#app.opts.plugin_openbrush_sync_category > 0 and '&category=' .. EscapeFragment(app.opts.plugin_openbrush_sync_category) or '')
.. (#app.opts.plugin_openbrush_sync_keywords > 0 and '&keywords=' .. EscapeFragment(app.opts.plugin_openbrush_sync_keywords) or '')
.. (#app.opts.plugin_openbrush_sync_triangle_max > 0 and '&triangleCountMax=' .. EscapeFragment(app.opts.plugin_openbrush_sync_triangle_max) or '')
- .. (app.opts.plugin_openbrush_sync_strategy == 'mirror' and '&license=ALL_CC' or '' )
+ .. (#app.opts.plugin_openbrush_sync_license > 0 and '&license=' .. app.opts.plugin_openbrush_sync_license or '' )
.. (app.opts.plugin_openbrush_sync_collection == 'enabled' and '&inCollection=true' or '' )
.. (#app.opts.plugin_openbrush_sync_maxitems > 0 and '&pageSize=' .. EscapeFragment(app.opts.plugin_openbrush_sync_maxitems) or '' )
-- TODO: filter AFTER the request
@@ -243,6 +223,7 @@ local plugin = {
return folder
end,
+ -- expected by src/.lua/apiSync.lua
fetch = function(url,opts)
opts = opts or {}
if not opts.body then
@@ -255,6 +236,7 @@ local plugin = {
return DecodeJson(opts.body)
end,
+ -- expected by src/.lua/apiSync.lua
download = function(t,tag)
local me = app.plugin.openbrush
local synced = 0
@@ -292,11 +274,13 @@ local plugin = {
sync = false -- already finished
end
end
- if sync or app.opts.plugin_openbrush_sync_bruteforce == 'enabled' then
+ if sync then
+ print('â ' .. asset.displayName .. ' (syncing) #openbrush')
util.writefile( jsonfile, EncodeJson(asset) )
local rootfile = dirnameFull .. '/' .. f.root.url:gsub(".*/","")
- local thumbnailfile = dirnameFull .. '.' .. asset.thumbnail.url:gsub(".*%.",'')
- if app.opts.plugin_openbrush_layout == 'portals' then
+ local thumbnailfile = ''
+ if asset.thumbnail and asset.thumbnail.url then
+ thumbnailfile = dirnameFull .. '.' .. asset.thumbnail.url:gsub(".*%.",'')
print('đ¤ fetch ' .. asset.thumbnail.url)
os.execute('wget "' ..asset.thumbnail.url .. '" -O "' .. thumbnailfile .. '"')
end
@@ -311,7 +295,7 @@ local plugin = {
end
synced = synced + 1
else
- print('[openbrush.lua] ' .. asset.displayName .. ' is up to date')
+ print('âšī¸ ' .. asset.displayName .. ' (up to date) #openbrush')
end
else
print('[openbrush.lua] error: no suitable format found for ' .. asset.displayName .. ' ' .. asset.assetId)
diff --git a/src/plugin/scheduler.lua b/src/plugin/scheduler.lua
index df79ed4..a31de3e 100644
--- a/src/plugin/scheduler.lua
+++ b/src/plugin/scheduler.lua
@@ -47,6 +47,8 @@ return {
if pid ~= nil then
unix.kill( pid, unix.SIGTERM)
end
+ print("gracefully stopping child-processes")
+ unix.wait()
unix.exit()
end)
end