feat: add social hub and stream cast modules with initialization, rendering, and scheduling functionalities

This commit is contained in:
2025-12-29 23:57:08 +00:00
parent 079bc3521c
commit 88763fd97d
10 changed files with 325 additions and 43 deletions

View File

@@ -0,0 +1,48 @@
-- Post composer utilities
local M = {}
function M.render()
return {
type = "composer",
children = {
{
type = "textarea",
props = {
placeholder = "What's on your mind?",
name = "content",
rows = 3
}
},
{
type = "composer_actions",
children = {
{ type = "button", props = { icon = "image", label = "Media" } },
{ type = "button", props = { icon = "smile", label = "Emoji" } },
{ type = "button", props = { variant = "primary", label = "Post" } }
}
}
}
}
end
function M.validate(content)
if not content or content == "" then
return { valid = false, error = "Post cannot be empty" }
end
if #content > 500 then
return { valid = false, error = "Post too long (max 500 chars)" }
end
return { valid = true }
end
function M.submit(content, media)
return {
action = "create_post",
data = {
content = content,
media = media or {}
}
}
end
return M

View File

@@ -0,0 +1,41 @@
-- Social feed rendering
local M = {}
function M.render_post(post)
return {
type = "feed_post",
props = {
id = post.id,
author = post.author,
avatar = post.avatar,
content = post.content,
timestamp = post.created_at,
likes = post.likes or 0,
comments = post.comments or 0
}
}
end
function M.render_feed(posts)
local items = {}
for _, post in ipairs(posts) do
table.insert(items, M.render_post(post))
end
return {
type = "social_feed",
children = items
}
end
function M.empty_state()
return {
type = "empty_state",
props = {
icon = "inbox",
title = "No posts yet",
message = "Be the first to share something!"
}
}
end
return M

View File

@@ -0,0 +1,15 @@
-- Social Hub initialization
local M = {}
M.name = "social_hub"
M.version = "1.0.0"
function M.init()
return {
name = M.name,
version = M.version,
loaded = true
}
end
return M

View File

@@ -1,34 +1,28 @@
{
"scripts": [
{
"id": "init",
"name": "Social Hub Init",
"file": "init.lua",
"name": "init",
"category": "lifecycle",
"description": "Lifecycle hooks for package installation"
"description": "Initialize social hub module"
},
{
"file": "permissions.lua",
"name": "permissions",
"category": "security",
"description": "Role-based access rules for posting and moderation"
"id": "feed",
"name": "Feed Rendering",
"file": "feed.lua",
"description": "Social feed post rendering"
},
{
"file": "feed_rank.lua",
"name": "feed_rank",
"category": "ranking",
"description": "Score feed items based on recency and engagement"
"id": "composer",
"name": "Post Composer",
"file": "composer.lua",
"description": "Create and publish posts"
},
{
"file": "moderation.lua",
"name": "moderation",
"category": "moderation",
"description": "Flag content for review using lightweight heuristics"
},
{
"file": "analytics.lua",
"name": "analytics",
"category": "analytics",
"description": "Aggregate engagement signals for dashboards"
"id": "stats",
"name": "Social Stats",
"file": "stats.lua",
"description": "Social statistics display"
}
]
}

View File

@@ -0,0 +1,38 @@
-- Social statistics
local M = {}
function M.render_stat(label, value, icon)
return {
type = "stat_card",
props = {
label = label,
value = value,
icon = icon
}
}
end
function M.render_stats(data)
return {
type = "stats_grid",
columns = 3,
children = {
M.render_stat("Followers", data.followers or 0, "users"),
M.render_stat("Following", data.following or 0, "user-plus"),
M.render_stat("Posts", data.posts or 0, "file-text")
}
}
end
function M.render_hero(user)
return {
type = "hero_section",
children = {
{ type = "avatar", props = { src = user.avatar, size = "xl" } },
{ type = "heading", props = { level = 1, text = user.name } },
{ type = "text", props = { variant = "muted", text = user.bio } }
}
}
end
return M

View File

@@ -0,0 +1,15 @@
-- Stream Cast initialization
local M = {}
M.name = "stream_cast"
M.version = "1.0.0"
function M.init()
return {
name = M.name,
version = M.version,
loaded = true
}
end
return M

View File

@@ -1,34 +1,28 @@
{
"scripts": [
{
"id": "init",
"name": "Stream Cast Init",
"file": "init.lua",
"name": "init",
"category": "lifecycle",
"description": "Lifecycle hooks for installation and removal"
"description": "Initialize stream cast module"
},
{
"id": "player",
"name": "Stream Player",
"file": "player.lua",
"description": "Video player controls"
},
{
"id": "schedule",
"name": "Stream Schedule",
"file": "schedule.lua",
"name": "schedule",
"category": "automation",
"description": "Resolve the next scene based on the run of show"
"description": "Stream scheduling"
},
{
"file": "scene_router.lua",
"name": "scene_router",
"category": "broadcast",
"description": "Map scene names to output destinations"
},
{
"file": "permissions.lua",
"name": "permissions",
"category": "security",
"description": "Role checks for publishing and moderation"
},
{
"file": "audience_pulse.lua",
"name": "audience_pulse",
"category": "analytics",
"description": "Score audience engagement from live metrics"
"id": "scenes",
"name": "Scene Manager",
"file": "scenes.lua",
"description": "Stream scene management"
}
]
}

View File

@@ -0,0 +1,48 @@
-- Stream player controls
local M = {}
M.PLAYING = "playing"
M.PAUSED = "paused"
M.BUFFERING = "buffering"
M.OFFLINE = "offline"
function M.render(stream)
return {
type = "video_player",
props = {
src = stream.url,
poster = stream.thumbnail,
autoplay = true,
controls = true
}
}
end
function M.render_controls(state)
return {
type = "player_controls",
children = {
{ type = "button", props = { icon = state == M.PLAYING and "pause" or "play" } },
{ type = "volume_slider", props = { min = 0, max = 100 } },
{ type = "button", props = { icon = "maximize" } }
}
}
end
function M.render_status(state, viewers)
local colors = {
playing = "success",
paused = "warning",
buffering = "info",
offline = "error"
}
return {
type = "status_bar",
children = {
{ type = "badge", props = { label = state, color = colors[state] } },
{ type = "text", props = { text = viewers .. " viewers" } }
}
}
end
return M

View File

@@ -0,0 +1,44 @@
-- Scene management
local M = {}
function M.render_scene(scene)
return {
type = "scene_preview",
props = {
id = scene.id,
name = scene.name,
thumbnail = scene.thumbnail,
active = scene.active or false
}
}
end
function M.render_list(scenes)
local items = {}
for _, scene in ipairs(scenes) do
table.insert(items, M.render_scene(scene))
end
return {
type = "scene_list",
children = items
}
end
function M.switch(scene_id)
return {
action = "switch_scene",
scene_id = scene_id
}
end
function M.create(name, sources)
return {
action = "create_scene",
data = {
name = name,
sources = sources or {}
}
}
end
return M

View File

@@ -0,0 +1,45 @@
-- Stream scheduling
local M = {}
function M.render_item(stream)
return {
type = "schedule_item",
props = {
title = stream.title,
start_time = stream.start_time,
duration = stream.duration,
thumbnail = stream.thumbnail
}
}
end
function M.render_list(streams)
local items = {}
for _, stream in ipairs(streams) do
table.insert(items, M.render_item(stream))
end
return {
type = "schedule_list",
children = items
}
end
function M.create(data)
return {
action = "schedule_stream",
data = {
title = data.title,
start_time = data.start_time,
duration = data.duration or 60
}
}
end
function M.cancel(stream_id)
return {
action = "cancel_stream",
stream_id = stream_id
}
end
return M