A Kick channel is a stream as much as a chat, and the video was in a browser tab beside the window that had the conversation in it. Not a player of its own. The frame a call draws into is now its own thing - VideoStage - and a call and a stream are two sources feeding it: the same pane, the same corner it retreats to, the same minimise that puts the picture down without ending it, the same sizing. What differs is the pipe. A call is real-time media that arrives as a MediaStream on srcObject; a stream is one-to-many HLS off a CDN, which needs Media Source Extensions and so needs hls.js, and that is the only piece here a call has no use for. Receiving only, and one at a time: nothing broadcasts, nobody else is in it, and starting a stream during a call is refused rather than fought over - the picture has one place to go. Offered where the channel is, by right-clicking it, and only while there is something to watch: an offline channel's playlist is a signed URL to nothing, and an entry that fails a few seconds after being pressed is worse than one that isn't there. The same menu is how it stops. Capped below 1080p60. That rendition is 5.8 Mbps of 60fps decode beside a chat client, and the ladder underneath it still adapts. A refused segment is read as an expired token rather than a dead stream, and answered by loading whichever playback URL the daemon has since sent. Co-Authored-By: Claude Opus 5 <[email protected]>
100 lines
2.6 KiB
JSON
100 lines
2.6 KiB
JSON
{
|
|
"name": "moho",
|
|
"version": "0.1.0",
|
|
"description": "Unified desktop chat client for IRC, Discord, Sneedchat and Matrix",
|
|
"author": "Salastil",
|
|
"license": "GPL-3.0-or-later",
|
|
"homepage": "https://git.salastil.com/Salastil/moho",
|
|
"main": "./out/main/index.js",
|
|
"scripts": {
|
|
"dev": "electron-vite dev",
|
|
"build": "npm run typecheck && electron-vite build",
|
|
"start": "electron-vite preview",
|
|
"typecheck": "tsc --noEmit -p tsconfig.node.json && tsc --noEmit -p tsconfig.web.json",
|
|
"pack": "npm run daemon && npm run build && electron-builder --linux AppImage",
|
|
"pack:dir": "npm run daemon && npm run build && electron-builder --linux dir",
|
|
"daemon": "./scripts/build-daemon.sh",
|
|
"deploy": "npm run pack && ./scripts/install-desktop.sh",
|
|
"daemon:win": "./scripts/build-daemon-win.sh",
|
|
"pack:win": "npm run daemon:win && npm run build && electron-builder --win nsis"
|
|
},
|
|
"dependencies": {
|
|
"@electron-toolkit/preload": "^3.0.1",
|
|
"@electron-toolkit/utils": "^3.0.0"
|
|
},
|
|
"devDependencies": {
|
|
"@types/node": "^22.10.2",
|
|
"@types/react": "^18.3.17",
|
|
"@types/react-dom": "^18.3.5",
|
|
"@vitejs/plugin-react": "^4.3.4",
|
|
"electron": "^33.2.1",
|
|
"electron-builder": "^25.1.8",
|
|
"electron-vite": "^2.3.0",
|
|
"hls.js": "^1.7.2",
|
|
"react": "^18.3.1",
|
|
"react-dom": "^18.3.1",
|
|
"typescript": "^5.7.2",
|
|
"vite": "^5.4.11"
|
|
},
|
|
"build": {
|
|
"appId": "com.salastil.moho",
|
|
"productName": "moho",
|
|
"files": [
|
|
"out/**/*"
|
|
],
|
|
"extraResources": [
|
|
{
|
|
"from": "nobilis/resources/sneedchat-smilies",
|
|
"to": "sneedchat-smilies"
|
|
},
|
|
{
|
|
"from": "resources/icons",
|
|
"to": "icons"
|
|
}
|
|
],
|
|
"linux": {
|
|
"target": [
|
|
"AppImage"
|
|
],
|
|
"category": "Network",
|
|
"icon": "resources/icons/moho.png",
|
|
"desktop": {
|
|
"Name": "moho",
|
|
"Comment": "Unified chat client for IRC, Discord, Sneedchat and Matrix"
|
|
},
|
|
"extraResources": [
|
|
{
|
|
"from": "nobilis/target/release/nobilis",
|
|
"to": "nobilis"
|
|
}
|
|
]
|
|
},
|
|
"win": {
|
|
"target": [
|
|
{
|
|
"target": "nsis",
|
|
"arch": [
|
|
"x64"
|
|
]
|
|
}
|
|
],
|
|
"icon": "resources/icons/moho.png",
|
|
"extraResources": [
|
|
{
|
|
"from": "nobilis/target/release/nobilis.exe",
|
|
"to": "nobilis.exe"
|
|
}
|
|
]
|
|
},
|
|
"nsis": {
|
|
"oneClick": false,
|
|
"allowToChangeInstallationDirectory": true,
|
|
"perMachine": false
|
|
}
|
|
},
|
|
"allowScripts": {
|
|
"[email protected]": true,
|
|
"[email protected]": true
|
|
}
|
|
}
|