{"id":13406450,"url":"https://github.com/netless-io/netless-app","last_synced_at":"2025-04-09T19:17:37.573Z","repository":{"id":37632380,"uuid":"395988264","full_name":"netless-io/netless-app","owner":"netless-io","description":"Official Apps for the Agora Interactive Whiteboard.","archived":false,"fork":false,"pushed_at":"2025-04-08T02:51:06.000Z","size":56456,"stargazers_count":60,"open_issues_count":1,"forks_count":42,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-09T19:17:32.900Z","etag":null,"topics":["netless"],"latest_commit_sha":null,"homepage":"https://netless-io.github.io/netless-app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/netless-io.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-08-14T11:29:22.000Z","updated_at":"2025-02-19T08:36:32.000Z","dependencies_parsed_at":"2023-11-24T09:24:40.487Z","dependency_job_id":"e06809f1-d3ec-4885-b29c-f97b1b733c48","html_url":"https://github.com/netless-io/netless-app","commit_stats":{"total_commits":744,"total_committers":9,"mean_commits":82.66666666666667,"dds":"0.40591397849462363","last_synced_commit":"0f071f1414f67d0b21b8df393307972a8bb06200"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netless-io%2Fnetless-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netless-io%2Fnetless-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netless-io%2Fnetless-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netless-io%2Fnetless-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/netless-io","download_url":"https://codeload.github.com/netless-io/netless-app/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248094988,"owners_count":21046770,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["netless"],"created_at":"2024-07-30T19:02:30.643Z","updated_at":"2025-04-09T19:17:37.544Z","avatar_url":"https://github.com/netless-io.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# Netless App\n\nOfficial Apps for the Agora Interactive Whiteboard.\n\n## Installation:\n\n\u003e If you don't have pnpm installed:\n\u003e\n\u003e ```bash\n\u003e npm i -g pnpm\n\u003e ```\n\nClone or fork this project, at project root run:\n\n```bash\npnpm i\npnpm build-all\n```\n\n## Environment\n\nBy default the `playground` demo uses a shared [Agora Whiteboard](https://www.agora.io/en/products/interactive-whiteboard/) account.\n\nWe recommend you use your own. Please register a new account and create a new env file `packages/playground/.env.local`. See `packages/playground/.env.example` for reference.\n\n## Development\n\n```bash\npnpm dev\n```\n\n## Create A New App\n\n```bash\npnpm create-app\n```\n\n## Useful Context APIs\n\n### Replayable Synced Storages\n\nStorage that synced across clients. Operations on storages are kept which can be replayed.\n\n```js\n// Create a storage under \"counter\" namespace with default value.\n// You can create multiple storages under the same namespace.\n// They will share the same synced storage.\nconst storage1 = context.createStorage(\"counter\", { count: 1 });\n\n// Access states\nconsole.log(storage1.state.count); // 1\n\n// Listen to state changes\nconst storage1StateListenerDisposer = storage1.on(\"stateChanged\", diff =\u003e {\n  if (diff.count) {\n    console.log(diff.count.newValue, diff.count.oldValue);\n  }\n});\n\nconst sea = {\n  a: 1,\n  b: false,\n};\n\n// Only writable user can setState\nif (context.isWritable) {\n  // Similar to React setState, unchanged values will be filtered by a root-level shallow-compare.\n  storage1.setState({\n    count: 2,\n    disabled: true,\n    // Note that `setState` only performs root-level shallow-compare.\n    // Object `sea` will be compared with `===`.\n    // Keys of `sea` will not be compared!\n    sea,\n  });\n}\n\n// Remember to remove unused listener later\ncontext.emitter.on(\"destroy\", () =\u003e {\n  storage1StateListenerDisposer();\n});\n\ncontext.emitter.on(\"destroy\", () =\u003e {\n  stateListenerDisposer();\n});\n```\n\n### Replayable Client Messaging\n\nMessaging between clients. Note that client will also receive the message sent by itself.\n\n```js\nconst magixListenerDisposer = context.addMagixEventListener(\"ping\", message =\u003e {\n  console.log(\"Received Message\", message);\n});\n\nif (context.isWritable) {\n  context.dispatchMagixEvent(\"ping\", 22);\n}\n\ncontext.emitter.on(\"destroy\", () =\u003e {\n  magixListenerDisposer();\n});\n```\n\n## License\n\nThe MIT license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnetless-io%2Fnetless-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnetless-io%2Fnetless-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnetless-io%2Fnetless-app/lists"}