feat: show latest

This commit is contained in:
2023-01-21 16:09:35 +00:00
parent abeb2f5a6c
commit d66f9ab18d
13 changed files with 145 additions and 47 deletions

View File

@ -47,13 +47,13 @@ export default function useLoginFeed() {
const main = useSubscription(sub, { leaveOpen: true });
useEffect(() => {
let contactList = main.notes.filter(a => a.kind === EventKind.ContactList);
let notifications = main.notes.filter(a => a.kind === EventKind.TextNote);
let metadata = main.notes.filter(a => a.kind === EventKind.SetMetadata);
let contactList = main.store.notes.filter(a => a.kind === EventKind.ContactList);
let notifications = main.store.notes.filter(a => a.kind === EventKind.TextNote);
let metadata = main.store.notes.filter(a => a.kind === EventKind.SetMetadata);
let profiles = metadata.map(a => mapEventToProfile(a))
.filter(a => a !== undefined)
.map(a => a!);
let dms = main.notes.filter(a => a.kind === EventKind.DirectMessage);
let dms = main.store.notes.filter(a => a.kind === EventKind.DirectMessage);
for (let cl of contactList) {
if (cl.content !== "") {
@ -87,7 +87,7 @@ export default function useLoginFeed() {
}
}
})().catch(console.warn);
}, [main]);
}, [main.store]);
}
async function makeNotification(ev: TaggedRawEvent) {

View File

@ -13,27 +13,38 @@ export type UseSubscriptionOptions = {
}
interface ReducerArg {
type: "END" | "EVENT"
ev?: TaggedRawEvent,
type: "END" | "EVENT" | "CLEAR",
ev?: TaggedRawEvent | Array<TaggedRawEvent>,
end?: boolean
}
function notesReducer(state: NoteStore, arg: ReducerArg) {
if (arg.type === "END") {
state.end = arg.end!;
return state;
return {
notes: state.notes,
end: arg.end!
} as NoteStore;
}
let ev = arg.ev!;
if (state.notes.some(a => a.id === ev.id)) {
//state.notes.find(a => a.id == ev.id)?.relays?.push(ev.relays[0]);
return state;
if (arg.type === "CLEAR") {
return {
notes: [],
end: state.end,
} as NoteStore;
}
let evs = arg.ev!;
if (!Array.isArray(evs)) {
evs = [evs];
}
evs = evs.filter(a => !state.notes.some(b => b.id === a.id));
if (evs.length === 0) {
return state;
}
return {
notes: [
...state.notes,
ev
...evs
]
} as NoteStore;
}
@ -43,13 +54,19 @@ const initStore: NoteStore = {
end: false
};
export interface UseSubscriptionState {
store: NoteStore,
clear: () => void,
append: (notes: TaggedRawEvent[]) => void
}
/**
*
* @param {Subscriptions} sub
* @param {any} opt
* @returns
*/
export default function useSubscription(sub: Subscriptions | null, options?: UseSubscriptionOptions) {
export default function useSubscription(sub: Subscriptions | null, options?: UseSubscriptionOptions): UseSubscriptionState {
const [state, dispatch] = useReducer(notesReducer, initStore);
const [debounce, setDebounce] = useState<number>(0);
@ -91,5 +108,17 @@ export default function useSubscription(sub: Subscriptions | null, options?: Use
return () => clearTimeout(t);
}, [state]);
return useMemo(() => state, [debounce]);
const stateDebounced = useMemo(() => state, [debounce]);
return {
store: stateDebounced,
clear: () => {
dispatch({ type: "CLEAR" });
},
append: (n: TaggedRawEvent[]) => {
dispatch({
type: "EVENT",
ev: n
});
}
}
}

View File

@ -37,13 +37,13 @@ export default function useThreadFeed(id: u256) {
useEffect(() => {
// debounce
let t = setTimeout(() => {
let eTags = main.notes.map(a => a.tags.filter(b => b[0] === "e").map(b => b[1])).flat();
let ids = main.notes.map(a => a.id);
let eTags = main.store.notes.map(a => a.tags.filter(b => b[0] === "e").map(b => b[1])).flat();
let ids = main.store.notes.map(a => a.id);
let allEvents = new Set([...eTags, ...ids]);
addId(Array.from(allEvents));
}, 200);
return () => clearTimeout(t);
}, [main.notes]);
}, [main.store]);
return main;
}

View File

@ -19,13 +19,13 @@ export interface TimelineSubject {
export default function useTimelineFeed(subject: TimelineSubject, options: TimelineFeedOptions) {
const now = unixNow();
const [window, setWindow] = useState<number>(60 * 60);
const [window, setWindow] = useState<number>(60 * 10);
const [until, setUntil] = useState<number>(now);
const [since, setSince] = useState<number>(now - window);
const [trackingEvents, setTrackingEvent] = useState<u256[]>([]);
const pref = useSelector<RootState, UserPreferences>(s => s.login.preferences);
const sub = useMemo(() => {
function createSub() {
if (subject.type !== "global" && subject.items.length == 0) {
return null;
}
@ -43,22 +43,49 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel
break;
}
}
if (options.method === "LIMIT_UNTIL") {
sub.Until = until;
sub.Limit = 10;
} else {
sub.Since = since;
sub.Until = until;
if (since === undefined) {
sub.Limit = 50;
return sub;
}
const sub = useMemo(() => {
let sub = createSub();
if (sub) {
if (options.method === "LIMIT_UNTIL") {
sub.Until = until;
sub.Limit = 10;
} else {
sub.Since = since;
sub.Until = until;
if (since === undefined) {
sub.Limit = 50;
}
}
if (pref.autoShowLatest) {
// copy properties of main sub but with limit 0
// this will put latest directly into main feed
let latestSub = new Subscriptions();
latestSub.Ids = sub.Ids;
latestSub.Kinds = sub.Kinds;
latestSub.Limit = 0;
sub.AddSubscription(latestSub);
}
}
return sub;
}, [subject.type, subject.items, until, since, window]);
const main = useSubscription(sub, { leaveOpen: true });
const subRealtime = useMemo(() => {
let subLatest = createSub();
if (subLatest && !pref.autoShowLatest) {
subLatest.Id = `${subLatest.Id}:latest`;
subLatest.Limit = 0;
}
return subLatest;
}, [subject.type, subject.items]);
const latest = useSubscription(subRealtime, { leaveOpen: true });
const subNext = useMemo(() => {
if (trackingEvents.length > 0 && pref.enableReactions) {
let sub = new Subscriptions();
@ -73,26 +100,32 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel
const others = useSubscription(subNext, { leaveOpen: true });
useEffect(() => {
if (main.notes.length > 0) {
if (main.store.notes.length > 0) {
setTrackingEvent(s => {
let ids = main.notes.map(a => a.id);
let ids = main.store.notes.map(a => a.id);
let temp = new Set([...s, ...ids]);
return Array.from(temp);
});
}
}, [main.notes]);
}, [main.store]);
return {
main: main.notes,
others: others.notes,
main: main.store,
related: others.store,
latest: latest.store,
loadMore: () => {
console.debug("Timeline load more!")
if (options.method === "LIMIT_UNTIL") {
let oldest = main.notes.reduce((acc, v) => acc = v.created_at < acc ? v.created_at : acc, unixNow());
let oldest = main.store.notes.reduce((acc, v) => acc = v.created_at < acc ? v.created_at : acc, unixNow());
setUntil(oldest);
} else {
setUntil(s => s - window);
setSince(s => s - window);
}
},
showLatest: () => {
main.append(latest.store.notes);
latest.clear();
}
};
}