solid-chat 0.0.1 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,59 +2,137 @@
2
2
 
3
3
  Modern, decentralized chat app built on the [Solid](https://solidproject.org) protocol.
4
4
 
5
- 🌐 **Live App:** [solid-chat.com/app](https://solid-chat.com/app)
5
+ **Live App:** [solid-chat.com/app](https://solid-chat.com/app)
6
6
 
7
7
  ## Features
8
8
 
9
- - Clean, modern messenger-style UI
10
- - Decentralized - messages stored in your Solid pod
9
+ ### Core
10
+ - Clean, WhatsApp-style messenger UI
11
+ - Decentralized - messages stored in Solid pods
11
12
  - Implements the [Solid Chat specification](https://solid.github.io/chat/)
12
- - Works with any Solid pod provider
13
- - Clickable WebID links on author names
13
+ - Works with any Solid pod provider (solidweb.org, solidcommunity.net, inrupt.net, etc.)
14
14
  - No React/heavy frameworks - vanilla JS
15
15
 
16
+ ### Authentication
17
+ - Solid OIDC authentication
18
+ - Multi-provider support (enter any IDP)
19
+ - Persistent sessions
20
+
21
+ ### Real-time
22
+ - WebSocket updates (NSS `Updates-Via` header)
23
+ - WebSocketChannel2023 support (CSS/solidcommunity.net)
24
+ - Notification sounds when tab is hidden (toggleable)
25
+
26
+ ### Messaging
27
+ - Send and receive messages
28
+ - Edit your own messages (requires Write permission)
29
+ - Delete your own messages (requires Write permission)
30
+ - Simple markdown: `*bold*`, `_italic_`, `~strike~`, `` `code` ``, ` ```code blocks``` `
31
+ - Emoji picker
32
+ - Emoji reactions: 👍 ❤️ 😂 😮 😢 🎉
33
+
34
+ ### Media
35
+ - File upload to your pod (📎 button)
36
+ - Paste images directly (Ctrl+V)
37
+ - Auto-expand images, video, and audio inline
38
+ - Clickable URLs
39
+
40
+ ### Sidebar
41
+ - Chat list with recent chats
42
+ - Type Index auto-discovery of your chats
43
+ - Create new chats on your pod
44
+ - Manual chat URL addition
45
+ - Persistent storage (localStorage)
46
+
47
+ ### Sharing & Deep Links
48
+ - Share button (📋) copies shareable link
49
+ - Deep link support: `?chat=<url>` loads or creates chat
50
+ - Auto-create: links to your pod create rooms on demand
51
+ - Type Index registration for discoverability
52
+
53
+ ### UI/UX
54
+ - Avatar display from WebID profiles
55
+ - Clickable author names (links to WebID)
56
+ - Clickable timestamps (permalinks to message URI)
57
+ - "(edited)" indicator for edited messages
58
+ - Message count in header
59
+
16
60
  ## Quick Start
17
61
 
18
62
  ```bash
19
- # Clone the repo
63
+ # Run instantly (no clone needed)
64
+ npx solid-chat
65
+
66
+ # Or clone and run
20
67
  git clone https://github.com/solid-chat/app.git
21
68
  cd app
69
+ npm install
70
+ npm start
71
+ ```
72
+
73
+ ## Usage
74
+
75
+ 1. Enter your Solid IDP (e.g., `solidweb.org`) and click Login
76
+ 2. Select a chat from the sidebar or add a new one
77
+ 3. Start chatting!
22
78
 
23
- # Serve locally
24
- npx serve .
79
+ ### Default Global Chats
80
+ - `https://solid-chat.solidweb.org/public/global/chat.ttl` (faster)
81
+ - `https://solid-chat.solidcommunity.net/public/global/chat.ttl`
25
82
 
26
- # Open in browser
27
- open http://localhost:3000
83
+ ### Deep Links
84
+
85
+ Share chats with a URL:
86
+ ```
87
+ https://solid-chat.com/app?chat=https://you.solidweb.org/public/chats/my-room.ttl
28
88
  ```
29
89
 
30
- ## Usage
90
+ **Behavior:**
91
+ - If chat exists → loads it
92
+ - If chat doesn't exist AND it's your pod → creates it automatically
93
+ - Change one character → instant new room
31
94
 
32
- 1. Enter a Solid chat URI in the input field
33
- 2. Click "Load Chat" or press Enter
34
- 3. Messages from the chat will be displayed
95
+ **Create rooms on demand:**
96
+ ```
97
+ https://solid-chat.com/app?chat=https://you.pod/public/chats/meeting-monday.ttl
98
+ https://solid-chat.com/app?chat=https://you.pod/public/chats/meeting-tuesday.ttl
99
+ ```
35
100
 
36
- Example chat URIs:
37
- - `https://solidos.solidcommunity.net/Team/SolidOs%20team%20chat/2022/02/09/chat.ttl`
101
+ Click the share button (📋) in any chat to copy the shareable link.
38
102
 
39
103
  ## Chat Data Format
40
104
 
41
- The app expects Turtle/RDF data using standard Solid chat vocabularies:
105
+ Messages use standard Solid chat vocabularies (RDF/Turtle):
42
106
 
43
107
  ```turtle
44
- @prefix flow: <http://www.w3.org/2005/01/wf/flow#>.
45
108
  @prefix sioc: <http://rdfs.org/sioc/ns#>.
46
109
  @prefix dct: <http://purl.org/dc/terms/>.
47
110
  @prefix foaf: <http://xmlns.com/foaf/0.1/>.
48
111
 
49
- <#this>
50
- a <http://www.w3.org/ns/pim/meeting#LongChat> ;
51
- flow:message :msg1 .
52
-
53
- :msg1
54
- a flow:Message ;
112
+ <#msg-1234567890>
113
+ a <http://www.w3.org/2005/01/wf/flow#Message> ;
55
114
  sioc:content "Hello world!" ;
56
115
  dct:created "2024-12-30T10:00:00Z"^^xsd:dateTime ;
57
- foaf:maker <https://example.com/profile#me> .
116
+ foaf:maker <https://you.solidweb.org/profile/card#me> .
117
+ ```
118
+
119
+ Reactions use Schema.org:
120
+
121
+ ```turtle
122
+ @prefix schema: <http://schema.org/>.
123
+
124
+ <#reaction-1234567890>
125
+ a schema:ReactAction ;
126
+ schema:about <#msg-123> ;
127
+ schema:agent <https://you.solidweb.org/profile/card#me> ;
128
+ schema:name "👍" .
129
+ ```
130
+
131
+ ## Testing
132
+
133
+ ```bash
134
+ npm install
135
+ npm test
58
136
  ```
59
137
 
60
138
  ## Specification
@@ -63,11 +141,24 @@ This app implements the [Solid Chat specification](https://solid.github.io/chat/
63
141
 
64
142
  ## Roadmap
65
143
 
66
- - [ ] Solid OIDC authentication
67
- - [ ] Chat list sidebar
68
- - [ ] Create new chats
69
- - [ ] Real-time updates
70
- - [ ] Nostr DID integration
144
+ - [x] Solid OIDC authentication
145
+ - [x] Chat list sidebar
146
+ - [x] Real-time updates (WebSocket + WebSocketChannel2023)
147
+ - [x] Notification sounds
148
+ - [x] File upload
149
+ - [x] Image paste
150
+ - [x] Media auto-expand
151
+ - [x] Simple markdown
152
+ - [x] Edit/delete messages
153
+ - [x] Emoji reactions
154
+ - [x] Create new chats
155
+ - [x] Deep link sharing (`?chat=<url>`)
156
+ - [x] Type Index registration
157
+ - [ ] @mentions with notifications
158
+ - [ ] End-to-end encryption
159
+ - [ ] Mobile responsive sidebar
160
+ - [ ] Unread message badges
161
+ - [ ] Message search
71
162
 
72
163
  ## License
73
164
 
package/bin/cli.js ADDED
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { createServer } from 'http'
4
+ import { readFileSync, existsSync, statSync } from 'fs'
5
+ import { join, extname } from 'path'
6
+ import { fileURLToPath } from 'url'
7
+ import { dirname } from 'path'
8
+ import open from 'open'
9
+
10
+ const __filename = fileURLToPath(import.meta.url)
11
+ const __dirname = dirname(__filename)
12
+ const ROOT = join(__dirname, '..')
13
+
14
+ const MIME_TYPES = {
15
+ '.html': 'text/html',
16
+ '.js': 'text/javascript',
17
+ '.mjs': 'text/javascript',
18
+ '.css': 'text/css',
19
+ '.json': 'application/json',
20
+ '.png': 'image/png',
21
+ '.jpg': 'image/jpeg',
22
+ '.svg': 'image/svg+xml',
23
+ '.ico': 'image/x-icon',
24
+ '.woff': 'font/woff',
25
+ '.woff2': 'font/woff2',
26
+ '.ttf': 'font/ttf'
27
+ }
28
+
29
+ const port = parseInt(process.argv[2]) || 3000
30
+
31
+ const server = createServer((req, res) => {
32
+ let filePath = join(ROOT, req.url === '/' ? 'index.html' : req.url)
33
+
34
+ // Security: prevent directory traversal
35
+ if (!filePath.startsWith(ROOT)) {
36
+ res.writeHead(403)
37
+ res.end('Forbidden')
38
+ return
39
+ }
40
+
41
+ // Handle directory requests
42
+ if (existsSync(filePath) && statSync(filePath).isDirectory()) {
43
+ filePath = join(filePath, 'index.html')
44
+ }
45
+
46
+ const ext = extname(filePath).toLowerCase()
47
+ const contentType = MIME_TYPES[ext] || 'application/octet-stream'
48
+
49
+ try {
50
+ const content = readFileSync(filePath)
51
+ res.writeHead(200, { 'Content-Type': contentType })
52
+ res.end(content)
53
+ } catch (err) {
54
+ if (err.code === 'ENOENT') {
55
+ res.writeHead(404)
56
+ res.end('Not Found')
57
+ } else {
58
+ res.writeHead(500)
59
+ res.end('Server Error')
60
+ }
61
+ }
62
+ })
63
+
64
+ server.listen(port, () => {
65
+ const url = `http://localhost:${port}`
66
+ console.log(`
67
+ ╭─────────────────────────────────────╮
68
+ │ │
69
+ │ Solid Chat running at: │
70
+ │ ${url.padEnd(30)}│
71
+ │ │
72
+ │ Press Ctrl+C to stop │
73
+ │ │
74
+ ╰─────────────────────────────────────╯
75
+ `)
76
+ open(url)
77
+ })
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/icons/icon.svg ADDED
@@ -0,0 +1,22 @@
1
+ <svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#667eea"/>
5
+ <stop offset="100%" style="stop-color:#9f7aea"/>
6
+ </linearGradient>
7
+ </defs>
8
+
9
+ <!-- Background -->
10
+ <rect width="512" height="512" rx="96" fill="url(#bg)"/>
11
+
12
+ <!-- Chat bubble -->
13
+ <g transform="translate(96, 116)">
14
+ <rect x="0" y="0" width="320" height="220" rx="40" fill="rgba(255,255,255,0.95)"/>
15
+ <polygon points="40,220 40,280 100,220" fill="rgba(255,255,255,0.95)"/>
16
+
17
+ <!-- Three dots -->
18
+ <circle cx="100" cy="110" r="24" fill="#667eea"/>
19
+ <circle cx="160" cy="110" r="24" fill="#7c8fef"/>
20
+ <circle cx="220" cy="110" r="24" fill="#9f7aea"/>
21
+ </g>
22
+ </svg>