Skip to content

Commit

Permalink
Merge pull request #37 from FuBoTeam/feature/add-longer-reading-time-…
Browse files Browse the repository at this point in the history
…and-fix-tailing-brace
  • Loading branch information
ben196888 authored Feb 13, 2022
2 parents 420c8c2 + 77660fe commit ba6913b
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 18 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"dependencies": {
"blueimp-load-image": "^2.24.0",
"firebase": "^9.6.2",
"guesslanguage": "^0.2.0",
"node-sass": "^4.13.0",
"react": "^16.11.0",
"react-dom": "^16.11.0",
Expand Down
27 changes: 17 additions & 10 deletions src/Board/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect, useCallback } from 'react';
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { RouteComponentProps } from 'react-router';
import { logEvent } from 'firebase/analytics';
import './board.scss';
Expand All @@ -7,6 +7,7 @@ import { useAnalytics, useDatabase } from '../Provider/FirebaseApp';
import Dialog from './Dialog';
import { Background } from './Background';
import { subscribePost } from './subscribePost';
import { estimateReadingTime } from '../utils/estimateReadingTime';

const Board: React.FC<RouteComponentProps> = (props) => {
// TODO: remove this and find a proper filter way on GA
Expand All @@ -16,29 +17,35 @@ const Board: React.FC<RouteComponentProps> = (props) => {
}, [analytics]);

const [modalDisplay, setModalDisplay] = useState(false);
const openModalAndClose = useCallback<(timeout?: number) => void>((timeout = 5000) => {
const openModalAndClose = useCallback<(onClose: () => any, timeout?: number) => void>((onClose, timeout = 5000) => {
setModalDisplay(true);
setTimeout(() => {
setModalDisplay(false);
onClose();
}, timeout);
}, [setModalDisplay]);

const [post, setPost] = useState({});
const database = useDatabase();
const { next, unsubscribe } = useMemo(() => subscribePost(database), [database]);
const getNextPost = useCallback(() => {
setTimeout(() => {
const newPost = next();
setPost(newPost);
estimateReadingTime(newPost.greetings, (estimatedSecond) => {
const timeout = Math.max(estimatedSecond * 1000, 5000);
openModalAndClose(getNextPost, timeout);
});
}, 3000);
}, [openModalAndClose, next]);

useEffect(() => {
// subscribe post while component did mount
const unsubscribe = subscribePost(database)((newPost) => {
if (newPost) {
setPost(newPost);
openModalAndClose();
}
});
getNextPost();
return () => {
// unsubscribe post while component will unmount
unsubscribe();
};
}, [database, openModalAndClose]);
}, [getNextPost, unsubscribe]);

return (
<React.Fragment>
Expand Down
17 changes: 10 additions & 7 deletions src/Board/subscribePost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ const heap = newHeap<HeapNode>((node1, node2) => {
return false;
});

type PostListener = (post: WeddiApp.Post.Data) => any;
type NextFn = () => WeddiApp.Post.Data;
type UnsubscribeFn = () => void;

export const subscribePost = (database: Database) => (listener: PostListener): UnsubscribeFn => {
export const subscribePost = (database: Database): { unsubscribe: UnsubscribeFn; next: NextFn } => {
const postsPool: {[timestampId: string]: WeddiApp.Post.Data} = {};
let feeds: HeapNode[] = [];
listPosts(database).then(posts => {
Expand All @@ -58,21 +58,24 @@ export const subscribePost = (database: Database) => (listener: PostListener): U
});
});

const interval = setInterval(() => {
const next: NextFn = () => {
if (feeds.length === 0) {
// refill feeds with pool feeds
feeds = Object.keys(postsPool).map(postId => newHeapNode(1, postId));
heap.init(feeds);
}
const nextFeed = heap.pop(feeds);
if (nextFeed) {
listener(postsPool[nextFeed.timestampId]);
return postsPool[nextFeed.timestampId];
}
}, 8000);
throw new Error('queue is empty');
};

const unsubscribe: UnsubscribeFn = () => {
clearInterval(interval);
// TODO: unsub API
};
return unsubscribe;
return {
unsubscribe,
next,
};
};
2 changes: 1 addition & 1 deletion src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const writePost = (database: Database, postData: WeddiApp.Post.UserInput)
userAgent: navigator.userAgent,
id: postId
};
return set(databaseRef(database, `${configService.config.post.namespace}/posts/${postId}}`), wrappedPostData);
return set(databaseRef(database, `${configService.config.post.namespace}/posts/${postId}`), wrappedPostData);
};

export const onNewPost = (database: Database, callback: (post: WeddiApp.Post.Data) => any): void => {
Expand Down
8 changes: 8 additions & 0 deletions src/guessLanguage.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
declare module 'guesslanguage' {
export namespace guessLanguage {
export function detect(input: string, callback: (language: string) => any): void;
export function name(input: string, callback: (languageName: string) => any): void;
export function code(input: string, callback: (languageIANA: string) => any): void;
export function info(input: string, callback: (languageInfo: [string, string, string]) => any): void;
}
}
34 changes: 34 additions & 0 deletions src/utils/estimateReadingTime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import guessLanguage from 'guesslanguage';

// data from https://irisreading.com/average-reading-speed-in-various-languages/
const CharactersPerMin = {
default: 987,
Arabic: 612,
Chinese: 255,
Dutch: 978,
English: 987,
Finnish: 1078,
French: 998,
German: 920,
Hebrew: 833,
Italian: 950,
Japanese: 357,
Polish: 916,
Portuguese: 913,
Russian: 986,
Slovenian: 885,
Spanish: 1025,
Swedish: 917,
Turkish: 1054,
};

export function estimateReadingTime(paragraph: string, callback: (estimatedSecond: number) => any): void {
guessLanguage.guessLanguage.name(paragraph, (languageName: string) => {
const readingSpeedCharPerMin = languageName in CharactersPerMin ?
CharactersPerMin[languageName as keyof typeof CharactersPerMin] :
CharactersPerMin.default;

const second = Math.floor(paragraph.length / readingSpeedCharPerMin * 60);
callback(second);
});
}
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5727,6 +5727,11 @@ growly@^1.3.0:
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=

guesslanguage@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/guesslanguage/-/guesslanguage-0.2.0.tgz#e5e4758a3d751ba4dd23f49a331dcf22e290038c"
integrity sha1-5eR1ij11G6TdI/SaMx3PIuKQA4w=

[email protected]:
version "5.1.1"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274"
Expand Down

0 comments on commit ba6913b

Please sign in to comment.