Subreddits can now be displayed with lit
6
.gitignore
vendored
|
|
@ -1,7 +1,5 @@
|
|||
.vscode/
|
||||
|
||||
node_modules/
|
||||
|
||||
public/main.js
|
||||
|
||||
dist/main.js
|
||||
dist/main.css
|
||||
*.log
|
||||
0
public/404.html → dist/404.html
vendored
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
0
public/index.html → dist/index.html
vendored
|
|
@ -19,14 +19,14 @@
|
|||
"url": "https://github.com/JubbeArt/removeddit/issues"
|
||||
},
|
||||
"homepage": "https://github.com/JubbeArt/removeddit#readme",
|
||||
"standard": {
|
||||
"globals": ["localStorage", "fetch"]
|
||||
},
|
||||
"scripts": {
|
||||
"start": "webpack-dev-server --mode development",
|
||||
"build": "webpack --mode production",
|
||||
"build-sass": "sass --style compressed public/sass/index.sass public/main.css"
|
||||
},
|
||||
"standard": {
|
||||
"globals": ["localStorage", "fetch"]
|
||||
},
|
||||
"dependencies": {
|
||||
"lit-html": "^0.9.0",
|
||||
"navigo": "^7.1.1",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,40 @@
|
|||
import { getToken } from './token'
|
||||
// Change this to your own client ID: https://www.reddit.com/prefs/apps
|
||||
// The app NEEDS TO BE an installed app and NOT a web apps
|
||||
|
||||
// Current using dummy ID from throwaway
|
||||
const clientID = '33W8M1OOxPv80A'
|
||||
|
||||
// Token for reddit API
|
||||
let token
|
||||
|
||||
// Header for general api calls
|
||||
export const getAuth = () => (
|
||||
getToken()
|
||||
.then(token => ({
|
||||
headers: {
|
||||
Authorization: `bearer ${token}`,
|
||||
},
|
||||
}))
|
||||
)
|
||||
export const getAuth = () => {
|
||||
// We have already gotten a token
|
||||
if (token !== undefined) {
|
||||
return Promise.resolve(token)
|
||||
}
|
||||
|
||||
// Headers for getting reddit api token
|
||||
const tokenInit = {
|
||||
headers: {
|
||||
Authorization: `Basic ${btoa(`${clientID}:`)}`,
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
|
||||
},
|
||||
method: 'POST',
|
||||
body: `grant_type=${encodeURIComponent('https://oauth.reddit.com/grants/installed_client')}&device_id=DO_NOT_TRACK_THIS_DEVICE`
|
||||
}
|
||||
|
||||
return (
|
||||
fetch('https://www.reddit.com/api/v1/access_token', tokenInit)
|
||||
.then(response => response.json())
|
||||
.then(responseBody => {
|
||||
// Save token for later
|
||||
token = responseBody.access_token
|
||||
return {
|
||||
headers: {
|
||||
Authorization: `bearer ${token}`
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
// Change this to your own client ID: https://www.reddit.com/prefs/apps
|
||||
// The app NEEDS TO BE an installed app and NOT a web apps
|
||||
|
||||
// Current using dummy ID from throwaway
|
||||
export default '33W8M1OOxPv80A'
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { chunk, flatten, json } from 'utils'
|
||||
import { chunk, flatten } from '../../utils'
|
||||
import { getAuth } from './auth'
|
||||
|
||||
export const getComments = commentIDs => (
|
||||
|
|
@ -10,7 +10,7 @@ export const getComments = commentIDs => (
|
|||
|
||||
export const fetchComments = (commentIDs, auth) => (
|
||||
fetch(`https://oauth.reddit.com/api/info?id=${commentIDs.map(id => `t1_${id}`).join()}`, auth)
|
||||
.then(json)
|
||||
.then(response => response.json())
|
||||
.then(results => results.data.children)
|
||||
.then(commentsData => commentsData.map(commentData => commentData.data))
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { json } from 'utils'
|
||||
import { getAuth } from './auth'
|
||||
|
||||
const cachedThreads = {}
|
||||
|
|
@ -23,7 +22,7 @@ export const getThread = (subreddit, threadID, commentID = '') => {
|
|||
return (
|
||||
getAuth()
|
||||
.then(auth => fetch(url, auth))
|
||||
.then(json)
|
||||
.then(response => response.json())
|
||||
.then(thread => {
|
||||
// Create cache object for thread if it doesn't exists
|
||||
if (!cachedThreads.hasOwnProperty(threadID)) {
|
||||
|
|
@ -39,14 +38,13 @@ export const getThread = (subreddit, threadID, commentID = '') => {
|
|||
)
|
||||
}
|
||||
|
||||
|
||||
export const getThreads = threadIDs => {
|
||||
const threadString = threadIDs.map(id => `t3_${id}`).join()
|
||||
|
||||
return (
|
||||
getAuth()
|
||||
.then(auth => fetch(`https://oauth.reddit.com/api/info?id=${threadString}`, auth))
|
||||
.then(json)
|
||||
.then(response => response.json())
|
||||
.then(response => {
|
||||
const threads = response.data.children
|
||||
return threads.map(threadData => threadData.data)
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
import { json } from 'utils'
|
||||
import clientID from './clientID'
|
||||
|
||||
// Token for reddit API
|
||||
let token = null
|
||||
|
||||
// Headers for getting reddit api token
|
||||
const tokenInit = {
|
||||
headers: {
|
||||
Authorization: `Basic ${btoa(`${clientID}:`)}`,
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
|
||||
},
|
||||
method: 'POST',
|
||||
body: `grant_type=${encodeURIComponent('https://oauth.reddit.com/grants/installed_client')}&device_id=DO_NOT_TRACK_THIS_DEVICE`,
|
||||
}
|
||||
|
||||
export const getToken = () => {
|
||||
if (token !== null) {
|
||||
return Promise.resolve(token)
|
||||
}
|
||||
|
||||
return (
|
||||
fetch('https://www.reddit.com/api/v1/access_token', tokenInit)
|
||||
.then(json)
|
||||
.then(response => {
|
||||
token = response.access_token
|
||||
return token
|
||||
})
|
||||
)
|
||||
}
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
import { json } from 'utils'
|
||||
|
||||
const baseURL = 'https://removeddit.com/api'
|
||||
|
||||
export const getRemovedThreadIDs = (subreddit = '', page = 1) => (
|
||||
fetch(`${baseURL}/threads?subreddit=${subreddit}&page=${page - 1}`)
|
||||
.then(json)
|
||||
.then(response => response.json())
|
||||
)
|
||||
|
|
|
|||
16
src/core/subreddit.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import { getRemovedThreadIDs } from '../api/removeddit'
|
||||
import { getThreads } from '../api/reddit'
|
||||
|
||||
export default (subreddit = 'all', setState) => {
|
||||
subreddit = subreddit.toLowerCase() === 'all' ? '' : subreddit.toLowerCase()
|
||||
|
||||
getRemovedThreadIDs(subreddit)
|
||||
.then(threadIDs => getThreads(threadIDs))
|
||||
.then(threads => {
|
||||
threads.forEach(thread => {
|
||||
thread.removed = true
|
||||
thread.selftext = ''
|
||||
})
|
||||
setState({ threads })
|
||||
})
|
||||
}
|
||||
54
src/index.js
|
|
@ -1,52 +1,40 @@
|
|||
import { html, render } from 'lit-html'
|
||||
import { render } from 'lit-html/lib/lit-extended'
|
||||
import Navigo from 'navigo'
|
||||
import aboutTemplate from './templates/about'
|
||||
import threadTemplate from './templates/thread'
|
||||
import subredditTemplate from './templates/subreddit'
|
||||
import {store} from 'state'
|
||||
// import p from 'snudown-js'
|
||||
import {store} from './state'
|
||||
import getThreads from './core/subreddit'
|
||||
|
||||
const router = new Navigo(window.location.origin)
|
||||
// router.updatePageLinks()
|
||||
|
||||
let currentTemplate = html``
|
||||
const main = document.getElementById('main')
|
||||
|
||||
const renderMain = () => render(currentTemplate(store.getState(), store.setState), main)
|
||||
store.subscribe(() => renderMain())
|
||||
// Causes a rerender of the currently selected template
|
||||
const renderPage = () => {
|
||||
const template = store.getState().template(store.getState(), store.setState)
|
||||
render(template, main)
|
||||
}
|
||||
|
||||
// Re-render page whenever state is changed
|
||||
store.subscribe(() => renderPage())
|
||||
|
||||
router.on({
|
||||
'/about': () => {
|
||||
currentTemplate = aboutTemplate
|
||||
renderMain()
|
||||
store.setState({template: aboutTemplate})
|
||||
},
|
||||
'/r/:subreddit/comments/:threadID/:junk/:commentID': params => {
|
||||
const {subreddit, threadID, commentID} = params
|
||||
store.setState({subreddit, threadID, commentID})
|
||||
currentTemplate = threadTemplate
|
||||
renderMain()
|
||||
'/r/:subreddit/comments/:threadID/:junk/:commentID': ({subreddit, threadID, commentID}) => {
|
||||
store.setState({template: threadTemplate, subreddit, threadID, commentID})
|
||||
},
|
||||
'/r/:subreddit/comments/:threadID/:junk': params => {
|
||||
const {subreddit, threadID} = params
|
||||
store.setState({subreddit, threadID, commentID: undefined})
|
||||
currentTemplate = threadTemplate
|
||||
renderMain()
|
||||
'/r/:subreddit/comments/:threadID*': ({subreddit, threadID}) => {
|
||||
store.setState({template: threadTemplate, subreddit, threadID, commentID: undefined})
|
||||
},
|
||||
'/r/:subreddit/comments/:threadID': params => {
|
||||
const {subreddit, threadID} = params
|
||||
store.setState({subreddit, threadID, commentID: undefined})
|
||||
currentTemplate = threadTemplate
|
||||
renderMain()
|
||||
},
|
||||
'/r/:subreddit': params => {
|
||||
const {subreddit} = params
|
||||
store.setState({subreddit, threadID: undefined, commentID: undefined})
|
||||
currentTemplate = subredditTemplate
|
||||
renderMain()
|
||||
'/r/:subreddit': ({subreddit}) => {
|
||||
store.setState({template: subredditTemplate, threads: [], subreddit, threadID: undefined, commentID: undefined})
|
||||
getThreads(subreddit, store.setState)
|
||||
},
|
||||
'*': () => {
|
||||
store.setState({subreddit: 'all', threadID: undefined, commentID: undefined})
|
||||
currentTemplate = subredditTemplate
|
||||
renderMain()
|
||||
store.setState({template: subredditTemplate, threads: [], subreddit: 'all', threadID: undefined, commentID: undefined})
|
||||
getThreads('all', store.setState)
|
||||
}
|
||||
}).resolve()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { getRemovedThreadIDs } from 'api/removeddit'
|
||||
import { getThreads } from 'api/reddit'
|
||||
import { getRemovedThreadIDs } from '../api/removeddit'
|
||||
import { getThreads } from '../api/reddit'
|
||||
import Post from 'components/Post'
|
||||
|
||||
const getSubredditForAPI = props => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import {createStore} from './store'
|
||||
import {get, showFunctions, sortFunctions} from 'utils'
|
||||
import {html} from 'lit-html'
|
||||
import {get, showFunctions, sortFunctions} from '../utils'
|
||||
import {html} from 'lit-html/lib/lit-extended'
|
||||
|
||||
export const commentSort = {
|
||||
top: 'top',
|
||||
|
|
@ -33,8 +33,7 @@ export const store = createStore({
|
|||
.filter(showFunctions[store.getState().currentShow])
|
||||
.sort(sortFunctions[store.getState().currentSort])
|
||||
}
|
||||
|
||||
})
|
||||
}, ['commentSort', 'commentShow'])
|
||||
|
||||
export const stateImages = {
|
||||
loading: '/images/loading.gif',
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import {put} from 'utils'
|
||||
import {put} from '../utils'
|
||||
|
||||
export const createStore = (initState = {}, persistentKeys = []) => {
|
||||
let state = initState
|
||||
|
|
@ -31,10 +31,3 @@ export const createStore = (initState = {}, persistentKeys = []) => {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// export
|
||||
|
||||
// const saveState = {
|
||||
// commentSort: true,
|
||||
// commentShow: true
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import {html} from 'lit-html'
|
||||
import {html} from 'lit-html/lib/lit-extended'
|
||||
|
||||
export default () => html`
|
||||
<div id="main-box">
|
||||
|
|
|
|||
20
src/templates/subreddit/index.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { html } from 'lit-html/lib/lit-extended'
|
||||
import post from '../thread/post'
|
||||
|
||||
export default (state, setState) => {
|
||||
const { subreddit, threads } = state
|
||||
const subredditLink = `/r/${subreddit}`
|
||||
|
||||
return (
|
||||
html`
|
||||
<div class="subreddit-box">
|
||||
<a href="${subredditLink}" class="subreddit-title" data-navigo>${subredditLink}</Link>
|
||||
<span class="space" />
|
||||
<a href="${`https://www.reddit.com${subredditLink}`}" class="subreddit-title-link">reddit</a>
|
||||
<span class="space" />
|
||||
<a href="${`https://snew.github.io${subredditLink}`}" class="subreddit-title-link">ceddit</a>
|
||||
</div>
|
||||
${threads.map(thread => post(thread))}
|
||||
`
|
||||
)
|
||||
}
|
||||
3
src/templates/thread/index.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import { html } from 'lit-html/lib/lit-extended'
|
||||
|
||||
export default () => html`<h1>thread</h1>`
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import {html} from 'lit-html'
|
||||
import {html} from 'lit-html/lib/lit-extended'
|
||||
|
||||
import { prettyScore, prettyDate, parse, redditThumbnails, isDeleted } from 'utils'
|
||||
import { prettyScore, prettyDate, parse, redditThumbnails, isDeleted } from '../../utils'
|
||||
|
||||
export default (props) => {
|
||||
if (!props.title) {
|
||||
|
|
@ -15,7 +15,7 @@ export default (props) => {
|
|||
let thumbnail
|
||||
|
||||
if (redditThumbnails.includes(props.thumbnail)) {
|
||||
thumbnail = html`<a href="${url}" class="${`thumbnail thumbnail-${props.thumbnail}`}"></a>`
|
||||
thumbnail = html`<a href="${url}" class$="${`thumbnail thumbnail-${props.thumbnail}`}"></a>`
|
||||
} else if (props.thumbnail !== '') {
|
||||
thumbnail = html`
|
||||
<a href="${url}">
|
||||
|
|
@ -25,7 +25,7 @@ export default (props) => {
|
|||
}
|
||||
|
||||
return html`
|
||||
<div class="${`thread ${props.removed && 'removed'}`}">
|
||||
<div class$="${`thread ${props.removed && 'removed'}`}">
|
||||
${props.position &&
|
||||
html`<span class="post-rank">${props.position}</span>`}
|
||||
<div class="thread-score-box">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import SnuOwnd from 'snuownd'
|
||||
// const SnuOwnd = require('snudown-js')
|
||||
|
||||
const markdown = SnuOwnd.getParser()
|
||||
// const markdown = SnuOwnd.getParser()
|
||||
|
||||
// Flatten arrays one level
|
||||
export const flatten = arr => arr.reduce(
|
||||
|
|
@ -121,4 +121,5 @@ export const sortFunctions = {
|
|||
if (commentA.created_utc > commentB.created_utc) return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,8 @@
|
|||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'public')
|
||||
},
|
||||
devServer: {
|
||||
contentBase: path.resolve(__dirname, 'public'),
|
||||
contentBase: path.resolve(__dirname, 'dist'),
|
||||
historyApiFallback: true
|
||||
}
|
||||
}
|
||||
|
|
|
|||