Skip to content

Commit 2b5b280

Browse files
authored
Merge pull request #469 from solid/editChat-merging
Edit chat merging
2 parents fb2b21e + 870de62 commit 2b5b280

File tree

13 files changed

+1509
-594
lines changed

13 files changed

+1509
-594
lines changed

src/chat/bookmarks.js

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const $rdf = UI.rdf
2222
const BOOK = $rdf.Namespace('http://www.w3.org/2002/01/bookmark#')
2323
const BOOKMARK_ICON = 'noun_45961.svg'
2424

25-
const kb = store
2625
const label = utils.label
2726
const dom = window.document || null
2827

@@ -33,10 +32,10 @@ const dom = window.document || null
3332
*/
3433
function createIfNotExists (doc) {
3534
return new Promise(function (resolve, reject) {
36-
kb.fetcher.load(doc).then(
35+
store.fetcher.load(doc).then(
3736
response => {
3837
debug.log('createIfNotExists doc exists, all good ' + doc)
39-
// kb.fetcher.webOperation('HEAD', doc.uri).then(response => {
38+
// store.fetcher.webOperation('HEAD', doc.uri).then(response => {
4039
resolve(response)
4140
},
4241
err => {
@@ -45,15 +44,15 @@ function createIfNotExists (doc) {
4544
'createIfNotExists doc does NOT exist, will create... ' + doc
4645
)
4746

48-
kb.fetcher
47+
store.fetcher
4948
.webOperation('PUT', doc.uri, {
5049
data: '',
5150
contentType: 'text/turtle'
5251
})
5352
.then(
5453
response => {
5554
// fetcher.requested[doc.uri] = 'done' // do not need to read ?? but no headers
56-
delete kb.fetcher.requested[doc.uri] // delete cached 404 error
55+
delete store.fetcher.requested[doc.uri] // delete cached 404 error
5756
debug.log('createIfNotExists doc created ok ' + doc)
5857
resolve(response)
5958
},
@@ -76,7 +75,7 @@ function createIfNotExists (doc) {
7675
// @@@@ use the one in rdflib.js when it is avaiable and delete this
7776
function updatePromise (del, ins) {
7877
return new Promise(function (resolve, reject) {
79-
kb.updater.update(del, ins, function (uri, ok, errorBody) {
78+
store.updater.update(del, ins, function (uri, ok, errorBody) {
8079
if (!ok) {
8180
reject(new Error(errorBody))
8281
} else {
@@ -150,9 +149,9 @@ async function addBookmark (context, target) {
150149
const me = UI.authn.currentUser() // If already logged on
151150
if (!me) throw new Error('Must be logged on to add Bookmark')
152151

153-
const author = kb.any(target, ns.foaf('maker'))
152+
const author = store.any(target, ns.foaf('maker'))
154153
title =
155-
label(author) + ': ' + kb.anyValue(target, ns.sioc('content')).slice(0, 80) // @@ add chat title too?
154+
label(author) + ': ' + store.anyValue(target, ns.sioc('content')).slice(0, 80) // @@ add chat title too?
156155
const bookmarkDoc = context.bookmarkDocument
157156
const bookmark = UI.widgets.newThing(bookmarkDoc, title)
158157
const ins = [
@@ -174,8 +173,8 @@ async function addBookmark (context, target) {
174173
}
175174

176175
export async function toggleBookmark (userContext, target, bookmarkButton) {
177-
await kb.fetcher.load(userContext.bookmarkDocument)
178-
const bookmarks = kb.each(
176+
await store.fetcher.load(userContext.bookmarkDocument)
177+
const bookmarks = store.each(
179178
null,
180179
BOOK('recalls'),
181180
target,
@@ -186,7 +185,7 @@ export async function toggleBookmark (userContext, target, bookmarkButton) {
186185
if (!confirm('Delete bookmark on this?' + bookmarks.length)) return
187186
for (let i = 0; i < bookmarks.length; i++) {
188187
try {
189-
await updatePromise(kb.connectedStatements(bookmarks[i]), [])
188+
await updatePromise(store.connectedStatements(bookmarks[i]), [])
190189
bookmarkButton.style.backgroundColor = 'white'
191190
debug.log('Bookmark deleted: ' + bookmarks[i])
192191
} catch (e) {
@@ -203,8 +202,8 @@ export async function toggleBookmark (userContext, target, bookmarkButton) {
203202

204203
export async function renderBookmarksButton (userContext, target) {
205204
async function setBookmarkButtonColor (bookmarkButton) {
206-
await kb.fetcher.load(userContext.bookmarkDocument)
207-
const bookmarked = kb.any(
205+
await store.fetcher.load(userContext.bookmarkDocument)
206+
const bookmarked = store.any(
208207
null,
209208
BOOK('recalls'),
210209
bookmarkButton.target,

src/chat/chatLogic.js

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/**
2+
* Contains the [[ChatChannel]] class and logic for Solid Chat
3+
* @packageDocumentation
4+
*/
5+
6+
import * as debug from '../debug'
7+
import { authn } from '../authn/index'
8+
import { DateFolder } from './dateFolder'
9+
import { store } from '../logic'
10+
import * as ns from '../ns'
11+
import * as $rdf from 'rdflib' // pull in first avoid cross-refs
12+
import * as utils from '../utils'
13+
14+
/* The Solid logic for a 'LongChat'
15+
*/
16+
/**
17+
* Common code for a chat (discussion area of messages about something)
18+
* This version runs over a series of files for different time periods
19+
*
20+
* Parameters for the whole chat like its title are stored on
21+
* index.ttl#this and the chats messages are stored in YYYY/MM/DD/chat.ttl
22+
*
23+
*/
24+
25+
export class ChatChannel {
26+
constructor (channel, options) {
27+
this.channel = channel
28+
this.channelRoot = channel.doc()
29+
this.options = options
30+
this.dateFolder = new DateFolder(this.channelRoot, 'chat.ttl')
31+
this.div = null // : HTMLElement
32+
}
33+
34+
/* Store a new message in the web,
35+
*/
36+
async createMessage (text) {
37+
return this.updateMessage(text)
38+
}
39+
40+
/* Store a new message in the web,
41+
as a replacement for an existing one.
42+
The old one iis left, and the two are linked
43+
*/
44+
async updateMessage (text, oldMsg = null, deleteIt) {
45+
const sts = []
46+
const now = new Date()
47+
const timestamp = '' + now.getTime()
48+
const dateStamp = $rdf.term(now)
49+
const chatDocument = oldMsg ? oldMsg.doc() : this.dateFolder.leafDocumentFromDate(now)
50+
const message = store.sym(chatDocument.uri + '#' + 'Msg' + timestamp)
51+
// const content = store.literal(text)
52+
53+
const me = authn.currentUser() // If already logged on
54+
55+
if (oldMsg) { // edit message replaces old one
56+
sts.push($rdf.st(mostRecentVersion(oldMsg), ns.dct('isReplacedBy'), message, chatDocument))
57+
if (deleteIt) {
58+
sts.push($rdf.st(message, ns.schema('dateDeleted'), dateStamp, chatDocument))
59+
}
60+
} else { // link new message to channel
61+
sts.push($rdf.st(this.channel, ns.wf('message'), message, chatDocument))
62+
}
63+
sts.push(
64+
$rdf.st(message, ns.sioc('content'), store.literal(text), chatDocument)
65+
)
66+
sts.push(
67+
$rdf.st(message, ns.dct('created'), dateStamp, chatDocument)
68+
)
69+
if (me) {
70+
sts.push($rdf.st(message, ns.foaf('maker'), me, chatDocument))
71+
}
72+
try {
73+
await store.updater.update([], sts)
74+
} catch (err) {
75+
const msg = 'Error saving chat message: ' + err
76+
debug.warn(msg)
77+
alert(msg)
78+
throw new Error(msg)
79+
}
80+
return message
81+
}
82+
83+
/* Mark a message as deleted
84+
* Wee add a new version of the message,m witha deletion flag (deletion date)
85+
* so that the deletion can be revoked by adding another non-deleted update
86+
*/
87+
async deleteMessage (message) {
88+
return this.updateMessage('(message deleted)', message, true)
89+
}
90+
} // class ChatChannel
91+
92+
export function originalVersion (message) {
93+
let msg = message
94+
while (msg) {
95+
message = msg
96+
msg = store.any(null, ns.dct('isReplacedBy'), message, message.doc())
97+
}
98+
return message
99+
}
100+
101+
export function mostRecentVersion (message) {
102+
let msg = message
103+
while (msg) {
104+
message = msg
105+
msg = store.any(message, ns.dct('isReplacedBy'), null, message.doc())
106+
}
107+
return message
108+
}
109+
110+
export function isDeleted (message) {
111+
return store.holds(message, ns.schema('dateDeleted'), null, message.doc())
112+
}
113+
114+
export function isReplaced (message) {
115+
return store.holds(message, ns.dct('isReplacedBy'), null, message.doc())
116+
}
117+
118+
export function isHidden (message) {
119+
return this.isDeleted(message) || this.isReplaced(message)
120+
}
121+
122+
// A Nickname for a person
123+
124+
export function nick (person) {
125+
const s = store.any(person, ns.foaf('nick'))
126+
if (s) return '' + s.value
127+
return '' + utils.label(person)
128+
}
129+
130+
export async function _createIfNotExists (doc, contentType = 'text/turtle', data = '') {
131+
let response
132+
try {
133+
response = await store.fetcher.load(doc)
134+
} catch (err) {
135+
if (err.response.status === 404) {
136+
debug.log(
137+
'createIfNotExists: doc does NOT exist, will create... ' + doc
138+
)
139+
try {
140+
response = await store.fetcher.webOperation('PUT', doc.uri, {
141+
data,
142+
contentType
143+
})
144+
} catch (err) {
145+
debug.log('createIfNotExists doc FAILED: ' + doc + ': ' + err)
146+
throw err
147+
}
148+
delete store.fetcher.requested[doc.uri] // delete cached 404 error
149+
// debug.log('createIfNotExists doc created ok ' + doc)
150+
return response
151+
} else {
152+
debug.log(
153+
'createIfNotExists doc load error NOT 404: ' + doc + ': ' + err
154+
)
155+
throw err
156+
}
157+
}
158+
// debug.log('createIfNotExists: doc exists, all good: ' + doc)
159+
return response
160+
}
161+
// ends

0 commit comments

Comments
 (0)