checkpoint
This commit is contained in:
76
src/db.ts
76
src/db.ts
@@ -10,8 +10,9 @@
|
||||
// Efficiently storing data in indexdb: https://stackoverflow.com/a/62975917
|
||||
|
||||
const postStoreName: string = "posts";
|
||||
const tombStoneStoreName: string = "tombstones"
|
||||
const tombstoneStoreName: string = "tombstones"
|
||||
const followingStoreName: string = "following"
|
||||
const profileStoreName: string = "profiles"
|
||||
let keyBase = "dandelion_posts_v1_"
|
||||
let key = "";
|
||||
let version = 1;
|
||||
@@ -33,33 +34,58 @@ async function upgrade_0to1(db: IDBDatabase) {
|
||||
postsStore.createIndex("postIDIndex", "data.post_id", { unique: true });
|
||||
}
|
||||
|
||||
|
||||
|
||||
// let following = ['b38b623c-c3fa-4351-9cab-50233c99fa4e'];
|
||||
|
||||
// let profiles = [
|
||||
// {
|
||||
// id: 'b38b623c-c3fa-4351-9cab-50233c99fa4e',
|
||||
// name: 'Robert Anderberg',
|
||||
// handle: 'bobbydigitales',
|
||||
// avatar_image: new ArrayBuffer(1024),
|
||||
// banner_image: new ArrayBuffer(1024),
|
||||
// description: "A very nice person who never does anything wrong.",
|
||||
// }];
|
||||
|
||||
|
||||
// let tombstones = ['b38b623c-c3fa-4351-9cab-50233c99fa4e'];
|
||||
|
||||
async function upgrade_1to2(db: IDBDatabase) {
|
||||
console.log("Upgrading database from 1 to 2");
|
||||
console.log("Converting all image arraybuffers to Blobs")
|
||||
let followingStore = db.createObjectStore(followingStoreName, { keyPath: "id", autoIncrement: true });
|
||||
let profileStore = db.createObjectStore(profileStoreName, { keyPath: "id", autoIncrement: true });
|
||||
let tombstoneStore = db.createObjectStore(tombstoneStoreName, { keyPath: "id", autoIncrement: true });
|
||||
tombstoneStore.createIndex("postIDIndex", "data.post_id", { unique: true });
|
||||
|
||||
// TODO convert all images from arraybuffers to blobs
|
||||
let knownUsers = [...(await indexedDB.databases())].map((db) => db.name?.replace('user_', ''));
|
||||
if (knownUsers.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const userID of knownUsers as string[]) {
|
||||
console.log(`Converting images for user ${userID}`)
|
||||
let posts = await getAllData(userID);
|
||||
|
||||
for (const post of posts) {
|
||||
let image_data = post.data.image_data;
|
||||
if (image_data) {
|
||||
let blob = new Blob([image_data as ArrayBuffer]);
|
||||
post.data.image_data = blob;
|
||||
|
||||
// TODO get the format of a new post right
|
||||
addData(userID, post);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// async function upgrade_1to2(db: IDBDatabase) {
|
||||
// console.log("Upgrading database from 1 to 2");
|
||||
// console.log("Converting all image arraybuffers to Blobs")
|
||||
|
||||
// // TODO convert all images from arraybuffers to blobs
|
||||
// let knownUsers = [...(await indexedDB.databases())].map((db) => db.name?.replace('user_', ''));
|
||||
// if (knownUsers.length === 0) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// for (const userID of knownUsers as string[]) {
|
||||
// console.log(`Converting images for user ${userID}`)
|
||||
// let posts = await getAllData(userID);
|
||||
|
||||
// for (const post of posts) {
|
||||
// let image_data = post.data.image_data;
|
||||
// if (image_data) {
|
||||
// let blob = new Blob([image_data as ArrayBuffer]);
|
||||
// post.data.image_data = blob;
|
||||
|
||||
// // TODO get the format of a new post right
|
||||
// addData(userID, post);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
async function upgrade_2to3(db: IDBDatabase) {
|
||||
let followingStore = db.createObjectStore(followingStoreName, { keyPath: "id", autoIncrement: true });
|
||||
}
|
||||
@@ -89,7 +115,7 @@ export function openDatabase(userID: string): Promise<IDBDatabase> {
|
||||
if (!upgradeFunction) {
|
||||
throw new Error(`db: Don't have an upgrade function to go from version ${event.oldVersion} to version ${event.newVersion}`);
|
||||
}
|
||||
debugger;
|
||||
// debugger;
|
||||
await upgradeFunction(db);
|
||||
};
|
||||
|
||||
|
||||
85
src/main.ts
85
src/main.ts
@@ -16,13 +16,13 @@ Problems
|
||||
|
||||
user
|
||||
posts
|
||||
media
|
||||
tombstones
|
||||
following
|
||||
profile
|
||||
name
|
||||
description
|
||||
profile pic
|
||||
media
|
||||
tombstones
|
||||
following
|
||||
profile
|
||||
name
|
||||
description
|
||||
profile pic
|
||||
|
||||
|
||||
Restruucture the app around the data. App/WS split is messy. Clean it up.
|
||||
@@ -542,7 +542,7 @@ class wsConnection {
|
||||
knownUsers = knownUsers
|
||||
.filter(userID => this.shouldSyncUserID(userID))
|
||||
.filter(userID => !this.userBlockList.has(userID))
|
||||
.filter(async userID => (await getAllIds(userID)).length > 0); // TODO getting all the IDs is unecessary, replace it with a test to get a single ID.
|
||||
.filter(async userID => (await getAllIds(userID)).length > 0); // TODO:EASYOPT getting all the IDs is unecessary, replace it with a test to get a single ID.
|
||||
|
||||
console.log('Net: Sending known users', knownUsers.map(userID => logID(userID ?? "")));
|
||||
return await this.send({ type: "hello", user_id: this.userID, user_name: app.username, peer_id: this.peerID, peer_name: app.peername, known_users: knownUsers });
|
||||
@@ -615,7 +615,7 @@ class wsConnection {
|
||||
log("ws:connected");
|
||||
await this.sendHello();
|
||||
|
||||
// If we're running as a headless peer, send a hello message every 60 seconds to refresh the posts we have.
|
||||
// If we're running as a headless peer, send a hello message every N seconds to refresh the posts we have.
|
||||
let helloRefreshIntervalPeriod = 120;
|
||||
if (app.isHeadless) {
|
||||
console.log("wsConnection: Setting hello refresh interval to ", helloRefreshIntervalPeriod)
|
||||
@@ -1200,34 +1200,55 @@ class App {
|
||||
|
||||
}
|
||||
|
||||
button(elementName: string) {
|
||||
return document.getElementById(elementName) as HTMLButtonElement;
|
||||
}
|
||||
|
||||
div(elementName: string) {
|
||||
return document.getElementById(elementName) as HTMLDivElement;
|
||||
}
|
||||
|
||||
initButtons(userID: string, posts: StoragePost[], registration: ServiceWorkerRegistration | undefined) {
|
||||
// let font1Button = document.getElementById("button_font1") as HTMLButtonElement;
|
||||
// let font2Button = document.getElementById("button_font2") as HTMLButtonElement;
|
||||
// let importTweetsButton = document.getElementById("import_tweets") as HTMLButtonElement;
|
||||
let exportButton = document.getElementById("export_button") as HTMLButtonElement;
|
||||
// let toggleDark = document.getElementById('toggle_dark') as HTMLButtonElement;
|
||||
// let clearPostsButton = document.getElementById("clear_posts") as HTMLButtonElement;
|
||||
// let updateApp = document.getElementById("update_app") as HTMLButtonElement;
|
||||
// let ddlnLogoButton = document.getElementById('ddln_logo_button') as HTMLDivElement;
|
||||
let monitorButton = document.getElementById('monitor_button') as HTMLDivElement;
|
||||
let composeButton = document.getElementById('compose_button') as HTMLDivElement;
|
||||
// let addPic = document.getElementById('button_add_pic') as HTMLDivElement;
|
||||
let filePickerLabel = document.getElementById('file_input_label');
|
||||
let filePicker = document.getElementById('file_input') as HTMLInputElement;
|
||||
// let toggleDark = document.getElementById('toggle_dark') as HTMLButtonElement;
|
||||
|
||||
exportButton.addEventListener('click', async e => await this.exportPostsForUser(this.userID));
|
||||
|
||||
// toggleDark.addEventListener('click', () => {
|
||||
// document.documentElement.style.setProperty('--main-bg-color', 'white');
|
||||
// document.documentElement.style.setProperty('--main-fg-color', 'black');
|
||||
// })
|
||||
|
||||
let homeButton = this.div('home-button');
|
||||
homeButton.addEventListener('click', e => window.location.href = `${window.location.origin}/`)
|
||||
|
||||
let profileButton = this.div('profile-button');
|
||||
profileButton.addEventListener('click', e => window.location.href = `${window.location.origin}/user/${this.userID}`)
|
||||
|
||||
let monitorButton = this.div('monitor_button');
|
||||
monitorButton.addEventListener('click', async () => {
|
||||
navContainer.classList.toggle('active');
|
||||
this.showInfo()
|
||||
});
|
||||
|
||||
let navContainer = this.div('nav-container');
|
||||
let burgerMenuButton = this.div('burger-menu-button');
|
||||
burgerMenuButton.addEventListener('click', e => navContainer.classList.toggle('active'));
|
||||
|
||||
let exportButton = this.button("export-button");
|
||||
exportButton.addEventListener('click', async e => await this.exportPostsForUser(this.userID));
|
||||
|
||||
let composeButton = this.div('compose-button');
|
||||
composeButton.addEventListener('click', e => {
|
||||
document.getElementById('compose')!.style.display = 'block';
|
||||
document.getElementById('textarea_post')?.focus();
|
||||
});
|
||||
|
||||
|
||||
let filePicker = document.getElementById('file-input') as HTMLInputElement;
|
||||
filePicker?.addEventListener('change', async (event: any) => {
|
||||
for (let file of filePicker.files as any) {
|
||||
let buffer = await file.arrayBuffer();
|
||||
@@ -1238,6 +1259,7 @@ class App {
|
||||
filePicker.value = '';
|
||||
});
|
||||
|
||||
let filePickerLabel = document.getElementById('file-input-label');
|
||||
filePickerLabel?.addEventListener('click', () => {
|
||||
console.log("Add pic...")
|
||||
})
|
||||
@@ -1301,9 +1323,6 @@ class App {
|
||||
// this.showInfo()
|
||||
// });
|
||||
|
||||
monitorButton.addEventListener('click', async () => {
|
||||
this.showInfo()
|
||||
});
|
||||
}
|
||||
|
||||
async getPostsForFeed() {
|
||||
@@ -1311,7 +1330,7 @@ class App {
|
||||
// get N posts from each user and sort them by date.
|
||||
// This isn't really going to work very well.
|
||||
// Eventually we'll need a db that only has followed user posts so we can get them chronologically
|
||||
//
|
||||
//
|
||||
let posts: StoragePost[] = [];
|
||||
for (let followedID of this.following.keys()) {
|
||||
posts = posts.concat(await getData(followedID, new Date(2022, 8), new Date()));
|
||||
@@ -1326,6 +1345,7 @@ class App {
|
||||
|
||||
async loadFollowersFromStorage(userID: string): Promise<string[]> {
|
||||
|
||||
// Rob
|
||||
if (userID === 'b38b623c-c3fa-4351-9cab-50233c99fa4e') {
|
||||
return [
|
||||
'b38b623c-c3fa-4351-9cab-50233c99fa4e',
|
||||
@@ -1337,6 +1357,7 @@ class App {
|
||||
]
|
||||
}
|
||||
|
||||
// Martin
|
||||
if (userID === '05a495a0-0dd8-4186-94c3-b8309ba6fc4c') {
|
||||
return [
|
||||
'b38b623c-c3fa-4351-9cab-50233c99fa4e',
|
||||
@@ -1344,6 +1365,15 @@ class App {
|
||||
]
|
||||
}
|
||||
|
||||
// Fiona
|
||||
if (userID === '8f6802be-c3b6-46c1-969c-5f90cbe01479') {
|
||||
return [
|
||||
'b38b623c-c3fa-4351-9cab-50233c99fa4e', // Rob
|
||||
'a0e42390-08b5-4b07-bc2b-787f8e5f1297', // BMO
|
||||
'05a495a0-0dd8-4186-94c3-b8309ba6fc4c', // Martin
|
||||
]
|
||||
}
|
||||
|
||||
return ['a0e42390-08b5-4b07-bc2b-787f8e5f1297']; // Follow BMO by default :)
|
||||
}
|
||||
|
||||
@@ -1352,7 +1382,7 @@ class App {
|
||||
this.timerStart();
|
||||
let posts: StoragePost[] = [];
|
||||
|
||||
// if (postID) {
|
||||
// if (postID) {
|
||||
// posts = await gePostForUser(userID, postID);
|
||||
// }
|
||||
|
||||
@@ -1389,7 +1419,8 @@ class App {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
console.log(`https://ddln.app/user/${userID}`);
|
||||
console.log(`${document.location.origin}/user/${userID}`);
|
||||
|
||||
// console.log(`https://ddln.app/${this.username}/${uuidToBase58(userID)}`, userID);
|
||||
}
|
||||
|
||||
@@ -1544,7 +1575,7 @@ class App {
|
||||
this.username = this.getUsername();
|
||||
await this.initDB();
|
||||
|
||||
this.connectURL = `https://${document.location.hostname}/connect/${this.userID}`;
|
||||
this.connectURL = `${document.location.origin}/connect/${this.userID}`;
|
||||
document.getElementById('connectURL')!.innerHTML = `<a href="${this.connectURL}">connect</a>`;
|
||||
|
||||
|
||||
@@ -1802,7 +1833,7 @@ class App {
|
||||
// let editButton = document.createElement('button'); editButton.innerText = 'edit';
|
||||
let shareButton = document.createElement('button'); shareButton.innerText = 'share';
|
||||
shareButton.onclick = async () => {
|
||||
let shareUrl = `https://${document.location.hostname}/user/${post.author_id}/post/${post.post_id}`;
|
||||
let shareUrl = `${document.location.origin}/user/${post.author_id}/post/${post.post_id}`;
|
||||
|
||||
await navigator.clipboard.writeText(shareUrl)
|
||||
};
|
||||
@@ -1824,7 +1855,7 @@ class App {
|
||||
markdown = markdown.replace("<iframe", `<iframe style="width:100%;height:50px;display:none" onblur="this.style.display = 'inline';"`);
|
||||
}
|
||||
|
||||
let userURL = `https://${document.location.hostname}/user/${post.author_id}/`
|
||||
let userURL = `${document.location.origin}/user/${post.author_id}/`
|
||||
|
||||
let postTemplate =
|
||||
`<div>${first ? '' : '<hr>'}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
class PeerManager {
|
||||
connect(peerID:string) {
|
||||
connect(peerID: string) {
|
||||
// Connect to the peer that has the peer id peerID
|
||||
}
|
||||
|
||||
disconnect(peerID:string) {
|
||||
disconnect(peerID: string) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class PeerConnection {
|
||||
static config = {
|
||||
iceServers: [
|
||||
@@ -17,13 +15,13 @@ class PeerConnection {
|
||||
{ urls: "stun:stun2.l.google.com" },
|
||||
{ urls: "stun:stun3.l.google.com" },
|
||||
{ urls: "stun:stun4.l.google.com" },
|
||||
],};
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const config = {
|
||||
iceServers: [{ urls: "stun:stun.mystunserver.tld" }],
|
||||
};
|
||||
@@ -31,7 +29,7 @@ const config = {
|
||||
let polite = true;
|
||||
|
||||
// const signaler = new SignalingChannel();
|
||||
const signaler:any = {}
|
||||
const signaler: any = {}
|
||||
const pc = new RTCPeerConnection(config);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user