2026-07-23 15:20:25 +02:00
|
|
|
|
local dir = require "opendirectory"
|
|
|
|
|
|
|
2026-07-28 08:50:24 +02:00
|
|
|
|
app.on('init', function()
|
|
|
|
|
|
print("scanning experiences (this make take a while..)")
|
2026-07-28 16:41:07 +02:00
|
|
|
|
app.opts.plugin_diskscan_dirname = app.opts.plugin_diskscan_dir:gsub("^[.]?[/]?","")
|
2026-07-28 08:50:24 +02:00
|
|
|
|
app.plugin.diskscan.scan(app.opts.plugin_diskscan_dir)
|
|
|
|
|
|
end)
|
|
|
|
|
|
|
2026-07-23 18:17:55 +02:00
|
|
|
|
-- this registers the plugin UI /funcs
|
|
|
|
|
|
return {
|
2026-07-29 22:44:24 +02:00
|
|
|
|
name = "Local Content",
|
2026-07-24 21:43:36 +02:00
|
|
|
|
info = '',
|
2026-07-23 18:17:55 +02:00
|
|
|
|
opts = {
|
|
|
|
|
|
{
|
|
|
|
|
|
key='app.opts.plugin_diskscan_dir',
|
|
|
|
|
|
title='Directory',
|
|
|
|
|
|
info="Directory to scan for experiences (use '.' for current) ",
|
2026-07-24 17:06:31 +02:00
|
|
|
|
default="./myverse",
|
2026-07-23 18:17:55 +02:00
|
|
|
|
values=''
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2026-07-23 15:20:25 +02:00
|
|
|
|
shouldHideFile = function(name)
|
2026-07-24 17:06:31 +02:00
|
|
|
|
return name == ".." -- parent
|
2026-07-23 15:20:25 +02:00
|
|
|
|
or name == "util" -- repository
|
2026-07-24 17:06:31 +02:00
|
|
|
|
or name:match("^%.") -- hidden
|
|
|
|
|
|
or name == "src" -- repository
|
|
|
|
|
|
or name == "result" -- repository
|
2026-07-23 15:20:25 +02:00
|
|
|
|
end,
|
|
|
|
|
|
|
2026-07-28 17:55:51 +02:00
|
|
|
|
scan = function(scandir)
|
2026-07-23 18:17:55 +02:00
|
|
|
|
local me = app.plugin.diskscan
|
2026-07-28 17:55:51 +02:00
|
|
|
|
local seen = {symlinks={}}
|
2026-07-28 16:41:07 +02:00
|
|
|
|
-- ensure rootdir as experience
|
|
|
|
|
|
app.cache.items[ scandir ] = {
|
|
|
|
|
|
path = scandir,
|
2026-07-28 17:55:51 +02:00
|
|
|
|
url = "/" .. util.stripPath(scandir),
|
2026-07-28 16:41:07 +02:00
|
|
|
|
name = scandir:gsub(".*/",""),
|
2026-08-02 14:00:56 +02:00
|
|
|
|
title = scandir:gsub(".*/",""):gsub("-"," "),
|
2026-07-28 16:41:07 +02:00
|
|
|
|
file = { ino = scandir },
|
|
|
|
|
|
id = scandir
|
|
|
|
|
|
}
|
2026-07-28 17:55:51 +02:00
|
|
|
|
me.scanDir(scandir, nil, seen )
|
|
|
|
|
|
-- deal with (circular) symlinks
|
|
|
|
|
|
foreach( seen.symlinks, function(ino,experience)
|
|
|
|
|
|
if not me.shouldHideFile(experience.name) then
|
|
|
|
|
|
local refItem = seen[experience.id_target]
|
|
|
|
|
|
if refItem then
|
|
|
|
|
|
print("ℹ️ ".. experience.path )
|
|
|
|
|
|
print("✅ └─ plugin/diskscan: detected symlink..creating portal")
|
|
|
|
|
|
experience.file = refItem.file
|
|
|
|
|
|
experience.portal = refItem
|
|
|
|
|
|
app.pub("scan_experience", nil, experience)
|
|
|
|
|
|
app.cache.items[experience.id] = experience
|
|
|
|
|
|
end
|
|
|
|
|
|
end
|
|
|
|
|
|
end)
|
|
|
|
|
|
-- cleanup file handles
|
|
|
|
|
|
foreach( app.cache.items, function(k,v)
|
|
|
|
|
|
-- remove file attributes (which are closed already)
|
2026-08-02 14:00:56 +02:00
|
|
|
|
if v.file then
|
|
|
|
|
|
v.file.stat = nil
|
|
|
|
|
|
v.file.attr = nil
|
|
|
|
|
|
v.file.state = nil
|
|
|
|
|
|
end
|
2026-07-28 17:55:51 +02:00
|
|
|
|
end)
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
|
|
|
|
scanDir = function(scandir,parent,seen)
|
|
|
|
|
|
local me = app.plugin.diskscan
|
2026-07-28 16:41:07 +02:00
|
|
|
|
parent = parent or app.cache.items[scandir]
|
2026-07-23 15:20:25 +02:00
|
|
|
|
-- scan dirs
|
2026-07-28 17:55:51 +02:00
|
|
|
|
local scanFile = function(path,stat,state,name,kind,ino,off,attr,fullpath)
|
2026-07-24 17:06:31 +02:00
|
|
|
|
|
2026-07-28 17:55:51 +02:00
|
|
|
|
local experience = {
|
|
|
|
|
|
path = fullpath,
|
|
|
|
|
|
url = "/" .. util.stripPath(fullpath),
|
|
|
|
|
|
name = name,
|
2026-08-02 14:00:56 +02:00
|
|
|
|
title = name:gsub("-"," "),
|
2026-07-28 17:55:51 +02:00
|
|
|
|
sidecarfile = {},
|
2026-07-29 22:44:24 +02:00
|
|
|
|
thumbnail = '',
|
2026-07-28 17:55:51 +02:00
|
|
|
|
tag = {},
|
|
|
|
|
|
id = ino,
|
|
|
|
|
|
file = {stat=stat,state=state,kind=kind,ino=ino,off=off,attr=attr,fullpath=fullpath,name=name,path=path}
|
|
|
|
|
|
}
|
|
|
|
|
|
experience.parent = parent
|
2026-07-24 17:06:31 +02:00
|
|
|
|
|
2026-07-28 17:55:51 +02:00
|
|
|
|
if seen[ino] then return end -- dont process dirs/files twice
|
2026-07-24 17:06:31 +02:00
|
|
|
|
|
2026-07-28 17:55:51 +02:00
|
|
|
|
if (kind == unix.DT_LNK) then
|
|
|
|
|
|
local stat, err = unix.stat(fullpath)
|
2026-08-02 14:00:56 +02:00
|
|
|
|
if stat then
|
|
|
|
|
|
experience.id_target = stat:ino()
|
|
|
|
|
|
seen.symlinks[ ino ] = experience
|
|
|
|
|
|
end
|
2026-07-28 17:55:51 +02:00
|
|
|
|
return
|
|
|
|
|
|
end
|
2026-07-28 16:41:07 +02:00
|
|
|
|
|
2026-07-28 17:55:51 +02:00
|
|
|
|
-- found directory
|
|
|
|
|
|
if (kind == unix.DT_DIR and kind ~= unix.DT_LNK)
|
|
|
|
|
|
and not me.shouldHideFile(name) then
|
|
|
|
|
|
seen[ino] = experience -- prevent recursion with symlinks
|
|
|
|
|
|
print("✅ ".. fullpath .. " " ..ino)
|
2026-07-31 14:41:34 +02:00
|
|
|
|
experience.dir = true
|
|
|
|
|
|
experience.portal3D = true -- can be viewed as 3d portal
|
2026-07-28 17:55:51 +02:00
|
|
|
|
app.pub("scan_experience", nil, experience)
|
|
|
|
|
|
app.cache.items[ino] = experience
|
2026-08-02 14:00:56 +02:00
|
|
|
|
-- check for directory thumbnail sidecarfile
|
|
|
|
|
|
local thumbExt = {"png","jpg","webp"}
|
|
|
|
|
|
foreach( thumbExt, function(k,ext)
|
|
|
|
|
|
local thumbnailFile = fullpath .. '.' .. ext
|
|
|
|
|
|
if util.fileExist( thumbnailFile ) then
|
|
|
|
|
|
experience.thumbnail = "/" .. util.stripPath(thumbnailFile)
|
|
|
|
|
|
print("✅ └─ plugin/diskscan: detected .".. ext:lower() .. " thumbnail file: " .. thumbnailFile)
|
|
|
|
|
|
end
|
|
|
|
|
|
end)
|
|
|
|
|
|
-- scan children
|
2026-07-28 17:55:51 +02:00
|
|
|
|
me.scanDir(fullpath,experience,seen,symlinks)
|
|
|
|
|
|
end
|
2026-07-28 16:41:07 +02:00
|
|
|
|
|
2026-07-28 17:55:51 +02:00
|
|
|
|
---- found file
|
|
|
|
|
|
if (kind ~= unix.DT_DIR and kind ~= unix.DT_LNK)
|
|
|
|
|
|
and not me.shouldHideFile(name) then
|
|
|
|
|
|
seen[ino] = experience.file -- prevent recursion with symlinks
|
|
|
|
|
|
trace("ℹ️ ".. fullpath)
|
|
|
|
|
|
experience.tag.file = true
|
|
|
|
|
|
app.pub("scan_experience_file", nil, experience)
|
|
|
|
|
|
local size = attr:size()
|
2026-07-28 16:41:07 +02:00
|
|
|
|
end
|
|
|
|
|
|
end
|
2026-07-28 17:55:51 +02:00
|
|
|
|
|
2026-07-28 16:41:07 +02:00
|
|
|
|
local dref, derr;
|
2026-07-28 17:55:51 +02:00
|
|
|
|
dref, derr = dir.foreach( scandir, scanFile )
|
2026-07-23 18:17:55 +02:00
|
|
|
|
if not derr then dref:close() end
|
2026-07-23 15:20:25 +02:00
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
}
|