Setup of single store works for multiple timeline

This commit is contained in:
Zhiyuan Zheng 2020-10-24 02:47:57 +02:00
parent 83f6039ade
commit cda67d23f6
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
16 changed files with 334 additions and 330 deletions

View File

@ -1,6 +1,6 @@
import React from 'react'
import Main from './src/Main'
import Index from './src/Index'
const App = () => <Main />
const App = () => <Index />
export default App

305
package-lock.json generated
View File

@ -1707,13 +1707,6 @@
"query-string": "^6.13.5",
"react-is": "^16.13.0",
"use-subscription": "^1.4.0"
},
"dependencies": {
"escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
}
}
},
"@react-navigation/native": {
@ -1751,13 +1744,6 @@
"redux": "^4.0.0",
"redux-thunk": "^2.3.0",
"reselect": "^4.0.0"
},
"dependencies": {
"reselect": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz",
"integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA=="
}
}
},
"@types/hammerjs": {
@ -2048,6 +2034,60 @@
"pkg-up": "^3.1.0",
"reselect": "^4.0.0",
"resolve": "^1.13.1"
},
"dependencies": {
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"requires": {
"locate-path": "^3.0.0"
}
},
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dev": true,
"requires": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
}
},
"p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dev": true,
"requires": {
"p-limit": "^2.0.0"
}
},
"p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true
},
"pkg-up": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
"integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
"dev": true,
"requires": {
"find-up": "^3.0.0"
}
}
}
},
"babel-plugin-react-native-web": {
@ -2084,52 +2124,6 @@
"resolve": "^1.4.0"
}
},
"find-up": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
"requires": {
"locate-path": "^2.0.0"
}
},
"locate-path": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
"integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
"requires": {
"p-locate": "^2.0.0",
"path-exists": "^3.0.0"
}
},
"p-limit": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
"integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
"requires": {
"p-try": "^1.0.0"
}
},
"p-locate": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
"integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
"requires": {
"p-limit": "^1.1.0"
}
},
"p-try": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
},
"pkg-up": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
"integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
"requires": {
"find-up": "^2.1.0"
}
},
"reselect": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz",
@ -2420,9 +2414,9 @@
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
},
"caniuse-lite": {
"version": "1.0.30001148",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001148.tgz",
"integrity": "sha512-E66qcd0KMKZHNJQt9hiLZGE3J4zuTqE1OnU53miEVtylFbwOEmeA5OsRu90noZful+XGSQOni1aT2tiqu/9yYw=="
"version": "1.0.30001150",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001150.tgz",
"integrity": "sha512-kiNKvihW0m36UhAFnl7bOAv0i1K1f6wpfVtTF5O5O82XzgtBnb05V0XeV3oZ968vfg2sRNChsHw8ASH2hDfoYQ=="
},
"capture-exit": {
"version": "2.0.0",
@ -2440,6 +2434,13 @@
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"dependencies": {
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
}
}
},
"chardet": {
@ -2756,9 +2757,9 @@
}
},
"dayjs": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.9.3.tgz",
"integrity": "sha512-V+1SyIvkS+HmNbN1G7A9+ERbFTV9KTXu6Oor98v2xHmzzpp52OIJhQuJSTywWuBY5pyAEmlwbCi1Me87n/SLOw=="
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.9.4.tgz",
"integrity": "sha512-ABSF3alrldf7nM9sQ2U+Ln67NRwmzlLOqG7kK03kck0mw3wlSSEKv/XhKGGxUjQcS57QeiCyNdrFgtj9nWlrng=="
},
"debug": {
"version": "4.2.0",
@ -2929,9 +2930,9 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"electron-to-chromium": {
"version": "1.3.582",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.582.tgz",
"integrity": "sha512-0nCJ7cSqnkMC+kUuPs0YgklFHraWGl/xHqtZWWtOeVtyi+YqkoAOMGuZQad43DscXCQI/yizcTa3u6B5r+BLww=="
"version": "1.3.583",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.583.tgz",
"integrity": "sha512-L9BwLwJohjZW9mQESI79HRzhicPk1DFgM+8hOCfGgGCFEcA3Otpv7QK6SGtYoZvfQfE3wKLh0Hd5ptqUFv3gvQ=="
},
"emoji-regex": {
"version": "8.0.0",
@ -3067,9 +3068,9 @@
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
},
"esprima": {
"version": "4.0.1",
@ -3549,6 +3550,13 @@
"integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
"requires": {
"escape-string-regexp": "^1.0.5"
},
"dependencies": {
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
}
}
},
"file-uri-to-path": {
@ -3627,12 +3635,11 @@
}
},
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
"requires": {
"locate-path": "^3.0.0"
"locate-path": "^2.0.0"
}
},
"fontfaceobserver": {
@ -4586,12 +4593,11 @@
"integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="
},
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dev": true,
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
"integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
"requires": {
"p-locate": "^3.0.0",
"p-locate": "^2.0.0",
"path-exists": "^3.0.0"
}
},
@ -4832,6 +4838,11 @@
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
@ -5114,6 +5125,11 @@
"source-map": "^0.5.0"
}
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"json5": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
@ -5649,9 +5665,9 @@
"optional": true
},
"nanoid": {
"version": "3.1.13",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.13.tgz",
"integrity": "sha512-oYL7jWZUdScASxYOrcwE8EvISFGzO3/1g+t56vCyR0s2nrpmBcOc7hTAFJaVf6HMyEPJrnNelnjRnMN6KZnCPA=="
"version": "3.1.15",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.15.tgz",
"integrity": "sha512-n8rXUZ8UU3lV6+43atPrSizqzh25n1/f00Wx1sCiE7R1sSHytZLTTiQl8DjC4IDLOnEZDlgJhy0yO4VsIpMxow=="
},
"nanomatch": {
"version": "1.2.13",
@ -5891,28 +5907,25 @@
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
},
"p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
"integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
"requires": {
"p-try": "^2.0.0"
"p-try": "^1.0.0"
}
},
"p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dev": true,
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
"integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
"requires": {
"p-limit": "^2.0.0"
"p-limit": "^1.1.0"
}
},
"p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
},
"parse-json": {
"version": "4.0.0",
@ -6025,12 +6038,11 @@
}
},
"pkg-up": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
"integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
"dev": true,
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
"integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
"requires": {
"find-up": "^3.0.0"
"find-up": "^2.1.0"
}
},
"plist": {
@ -6728,13 +6740,6 @@
"requires": {
"loose-envify": "^1.4.0",
"symbol-observable": "^1.2.0"
},
"dependencies": {
"symbol-observable": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
"integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
}
}
},
"redux-thunk": {
@ -6872,8 +6877,7 @@
"reselect": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz",
"integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==",
"dev": true
"integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA=="
},
"resolve": {
"version": "1.18.1",
@ -6945,6 +6949,13 @@
"integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==",
"requires": {
"symbol-observable": "1.0.1"
},
"dependencies": {
"symbol-observable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
"integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ="
}
}
},
"safe-buffer": {
@ -7419,61 +7430,21 @@
}
},
"string.prototype.trimend": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
"integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz",
"integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==",
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
},
"dependencies": {
"es-abstract": {
"version": "1.17.7",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
"integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
"is-regex": "^1.1.1",
"object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.1",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
}
}
"es-abstract": "^1.18.0-next.1"
}
},
"string.prototype.trimstart": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
"integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz",
"integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==",
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
},
"dependencies": {
"es-abstract": {
"version": "1.17.7",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
"integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
"is-regex": "^1.1.1",
"object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.1",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
}
}
"es-abstract": "^1.18.0-next.1"
}
},
"string_decoder": {
@ -7511,9 +7482,9 @@
}
},
"symbol-observable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
"integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ="
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
"integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
},
"temp": {
"version": "0.8.3",
@ -7823,9 +7794,9 @@
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
},
"use-subscription": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/use-subscription/-/use-subscription-1.4.1.tgz",
"integrity": "sha512-7+IIwDG/4JICrWHL/Q/ZPK5yozEnvRm6vHImu0LKwQlmWGKeiF7mbAenLlK/cTNXrTtXHU/SFASQHzB6+oSJMQ==",
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/use-subscription/-/use-subscription-1.5.0.tgz",
"integrity": "sha512-/FVRiB2I7NDjzWoNBYPt6YkkvleMm/lFtxj1hH6nX2TVrJ/5UTbovw9OE1efv2Zl0HoAYuTjM7zHd9OsABn5sg==",
"requires": {
"object-assign": "^4.1.1"
}

View File

@ -26,7 +26,7 @@
"react-native-render-html": "^4.2.4",
"react-native-safe-area-context": "3.1.4",
"react-native-screens": "~2.10.1",
"react-native-web": "~0.13.12",
"react-native-web": "~0.13.7",
"react-native-webview": "10.7.0",
"react-redux": "^7.2.1"
},

View File

@ -5,31 +5,29 @@ import { enableScreens } from 'react-native-screens'
enableScreens()
import React from 'react'
import store from './app/store'
import store from 'src/stacks/common/store'
import { Provider } from 'react-redux'
import { StatusBar } from 'expo-status-bar'
import MainTimeline from 'src/stacks/MainTimeline'
import PublicTimeline from 'src/stacks/PublicTimeline'
import Main from 'src/stacks/Main'
import Public from 'src/stacks/Public'
import Notifications from 'src/stacks/Notifications'
import Me from 'src/stacks/Me'
const Tab = createBottomTabNavigator()
export default function Main () {
export default function Index () {
return (
<>
<Provider store={store}>
<StatusBar style='auto' />
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name='MainTimeline' component={MainTimeline} />
<Tab.Screen name='PublicTimeline' component={PublicTimeline} />
<Tab.Screen name='Main' component={Main} />
<Tab.Screen name='Public' component={Public} />
{/* <Tab.Screen name='Notifications' component={Notifications} /> */}
<Tab.Screen name='Me' component={Me} />
</Tab.Navigator>
</NavigationContainer>
</Provider>
</>
)
}

View File

@ -1,12 +1,6 @@
export async function client (
instance,
endpoint,
query,
{ body, ...customConfig } = {}
) {
if (!instance || !endpoint) {
console.error('Missing instance or endpoint.')
return Promise.reject('Missing instance or endpoint.')
export async function client (url, query, { body, ...customConfig } = {}) {
if (!url) {
return Promise.reject('Missing URL.')
}
const headers = { 'Content-Type': 'application/json' }
@ -25,8 +19,8 @@ export async function client (
let data
try {
const response = await fetch(
`https://${instance}/api/v1/${endpoint}${
query
`https://${url}${
Object.keys(query).length
? `?${Object.keys(query)
.map(key => `${key}=${query[key]}`)
.join('&')}`

View File

@ -1,16 +0,0 @@
import { configureStore } from '@reduxjs/toolkit'
import genericTimelineSlice from 'src/stacks/common/timelineSlice'
export default configureStore({
reducer: {
'social.xmflsct.com': genericTimelineSlice('social.xmflsct.com').slice
.reducer,
'm.cmx.im': genericTimelineSlice('m.cmx.im').slice.reducer
},
middleware: getDefaultMiddleware =>
getDefaultMiddleware({
immutableCheck: false,
serializableCheck: false
})
})

14
src/stacks/Main.jsx Normal file
View File

@ -0,0 +1,14 @@
import React from 'react'
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
import Following from 'src/stacks/Main/Following'
const MainStack = createNativeStackNavigator()
export default function Main () {
return (
<MainStack.Navigator>
<MainStack.Screen name='Following' component={Following} />
</MainStack.Navigator>
)
}

View File

@ -0,0 +1,7 @@
import React from 'react'
import Timeline from 'src/stacks/common/Timeline'
export default function Following () {
return <Timeline endpoint='home' />
}

View File

@ -1,18 +0,0 @@
import React from 'react'
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
import Timeline from 'src/stacks/common/Timeline'
const MainTimelineStack = createNativeStackNavigator()
function Base () {
return <Timeline instance='social.xmflsct.com' endpoint='home' />
}
export default function MainTimeline () {
return (
<MainTimelineStack.Navigator>
<MainTimelineStack.Screen name='Base' component={Base} />
</MainTimelineStack.Navigator>
)
}

14
src/stacks/Public.jsx Normal file
View File

@ -0,0 +1,14 @@
import React from 'react'
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
import CurrentPublic from 'src/stacks/Public/CurrentPublic'
const PublicStack = createNativeStackNavigator()
export default function PublicTimeline () {
return (
<PublicStack.Navigator>
<PublicStack.Screen name='CurrentPublic' component={CurrentPublic} />
</PublicStack.Navigator>
)
}

View File

@ -0,0 +1,7 @@
import React from 'react'
import Timeline from 'src/stacks/common/Timeline'
export default function CurrentPublic () {
return <Timeline endpoint='public' local />
}

View File

@ -1,20 +0,0 @@
import React from 'react'
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
import Timeline from 'src/stacks/common/Timeline'
const PublicTimelineStack = createNativeStackNavigator()
function Base () {
return <Timeline instance='social.xmflsct.com' endpoint='public' local />
}
export default function PublicTimeline () {
return (
<PublicTimelineStack.Navigator>
<PublicTimelineStack.Screen name='Base' component={Base} />
</PublicTimelineStack.Navigator>
)
}
// store by page maybe

View File

@ -1,23 +1,25 @@
import PropTypes from 'prop-types'
import React, { useEffect } from 'react'
import { ActivityIndicator, FlatList, View } from 'react-native'
import { useSelector, useDispatch } from 'react-redux'
import { connect, useSelector, useDispatch } from 'react-redux'
import TootTimeline from 'src/components/TootTimeline'
import { fetch, getToots, getStatus } from './timelineSlice'
import genericTimelineSlice from './timelineSlice'
export default function Timeline ({ instance, endpoint, local }) {
export default function Timeline ({ remote, endpoint, local }) {
const dispatch = useDispatch()
const toots = useSelector(genericTimelineSlice(instance).getToots)
const status = useSelector(genericTimelineSlice(instance).getStatus)
const toots = useSelector(state =>
getToots(state)({ remote, endpoint, local })
)
const status = useSelector(state =>
getStatus(state)({ remote, endpoint, local })
)
useEffect(() => {
if (status === 'idle') {
dispatch(genericTimelineSlice(instance).fetch({ endpoint, local }))
dispatch(fetch({ remote, endpoint, local }))
}
}, [status, dispatch])
let content
if (status === 'error') {
@ -31,22 +33,13 @@ export default function Timeline ({ instance, endpoint, local }) {
renderItem={TootTimeline}
onRefresh={() =>
dispatch(
genericTimelineSlice(instance).fetch({
endpoint,
local,
id: toots[0].id,
newer: true
})
fetch({ remote, endpoint, local, id: toots[0].id, newer: true })
)
}
refreshing={status === 'loading'}
onEndReached={() =>
dispatch(
genericTimelineSlice(instance).fetch({
endpoint,
local,
id: toots[toots.length - 1].id
})
fetch({ remote, endpoint, local, id: toots[toots.length - 1].id })
)
}
onEndReachedThreshold={0.5}
@ -61,6 +54,7 @@ export default function Timeline ({ instance, endpoint, local }) {
}
Timeline.propTypes = {
instance: PropTypes.string.isRequired,
public: PropTypes.bool
remote: PropTypes.bool,
endpoint: PropTypes.string.isRequired,
local: PropTypes.bool
}

View File

@ -0,0 +1,24 @@
import { createSlice } from '@reduxjs/toolkit'
const instanceInfoSlice = createSlice({
name: 'instanceInfo',
initialState: {},
reducers: {
// increment (state) {
// state.value++
// },
// decrement (state) {
// state.value--
// },
// incrementByAmount (state, action) {
// state.value += action.payload
// }
}
})
export const getCurrent = state => state.current
export const getCurrentToken = state => state.currentToken
export const getRemote = state => state.remote
// export const { increment, decrement, incrementByAmount } = counterSlice.actions
export default instanceInfoSlice.reducer

View File

@ -0,0 +1,30 @@
import { configureStore } from '@reduxjs/toolkit'
import instanceInfoSlice from 'src/stacks/common/instanceInfoSlice'
import timelineSlice from 'src/stacks/common/timelineSlice'
// get site information from local storage and pass to reducers
const preloadedState = {
instanceInfo: {
current: 'social.xmflsct.com',
currentToken: 'qjzJ0IjvZ1apsn0_wBkGcdjKgX7Dao9KEPhGwggPwAo',
remote: 'm.cmx.im'
}
}
const reducer = {
instanceInfo: instanceInfoSlice,
timelines: timelineSlice
}
// const middleware = getDefaultMiddleware =>
// getDefaultMiddleware({
// immutableCheck: false,
// serializableCheck: false
// })
export default configureStore({
preloadedState,
reducer,
// middleware
})

View File

@ -1,77 +1,82 @@
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import { client } from 'src/api/client'
import * as localStorage from 'src/utils/localStorage'
export default function genericTimelineSlice (instance) {
const fetch = createAsyncThunk(
'timeline/fetch',
async ({ endpoint, local, id, newer }) => {
if (!instance || !endpoint) console.error('Missing instance or endpoint.')
// Naming convention
// Following: home
// Local: home/local
// CurrentPublic: public/local
// RemotePublic: remote
let query = {}
if (local) query.local = 'true'
if (newer) {
query.since_id = id
} else {
if (id) {
query.max_id = id
const checkInstance = ({ remote, endpoint, local }) =>
remote ? 'remote' : `${endpoint}${local ? '/local' : ''}`
export const fetch = createAsyncThunk(
'timeline/fetch',
async ({ remote, endpoint, local, id, newer }, { getState }) => {
if (!endpoint) console.error('Missing endpoint')
const instance = remote
? `${getState().instanceInfo.remote}/api/v1/timelines/public`
: `${getState().instanceInfo.current}/api/v1/timelines/${endpoint}`
const query = {
...(local && { local: 'true' }),
...(newer ? { since_id: id } : id && { max_id: id })
}
const header = {
...(getState().instanceInfo.currentToken && {
headers: {
Authorization: `Bearer ${getState().instanceInfo.currentToken}`
}
}
let header
const instanceToken = await localStorage.getItem()
if (instanceToken) {
header = { headers: { Authorization: `Bearer ${instanceToken}` } }
}
return {
data: await client.get(
instance,
`timelines/${endpoint}`,
query,
header
),
newer: newer
}
})
}
)
const slice = createSlice({
name: instance,
initialState: {
toots: [],
status: 'idle',
error: null
},
extraReducers: {
[fetch.pending]: state => {
state.status = 'loading'
},
[fetch.fulfilled]: (state, action) => {
state.status = 'succeeded'
action.payload.newer
? state.toots.unshift(...action.payload.data)
: state.toots.push(...action.payload.data)
},
[fetch.rejected]: (state, action) => {
state.status = 'failed'
state.error = action.payload
}
}
})
getToots = state => state[instance].toots
getStatus = state => state[instance].status
return {
fetch,
slice,
getToots,
getStatus
return await client.get(instance, query, header)
}
}
)
// export const timelineSlice = genericTimelineSlice(data)
export const timelineSlice = createSlice({
name: 'timeline',
initialState: {
home: {
toots: [],
status: 'idle'
},
'home/local': {
toots: [],
status: 'idle'
},
'public/local': {
toots: [],
status: 'idle'
},
remote: {
toots: [],
status: 'idle'
}
},
extraReducers: {
[fetch.pending]: (state, action) => {
state[checkInstance(action.meta.arg)].status = 'loading'
},
[fetch.fulfilled]: (state, action) => {
state[checkInstance(action.meta.arg)].status = 'succeeded'
action.meta.arg.newer
? state[checkInstance(action.meta.arg)].toots.unshift(...action.payload)
: state[checkInstance(action.meta.arg)].toots.push(...action.payload)
},
[fetch.rejected]: (state, action) => {
console.error(action.error.message)
state[checkInstance(action.meta.arg)].status = 'failed'
}
}
})
// export default timelineSlice.reducer
export const getToots = state => instance =>
state.timelines[checkInstance(instance)].toots
export const getStatus = state => instance =>
state.timelines[checkInstance(instance)].status
export default timelineSlice.reducer