main.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. import NProgress from 'nprogress'
  2. import IO from 'socket.io-client'
  3. window.socket = IO()
  4. socket.on('disconnect', () => {
  5. socket.connect('http://localhost:3000', {
  6. reconnection: true,
  7. reconnectionDelay: 1000,
  8. reconnectionDelayMax : 5000,
  9. reconnectionAttempts: Infinity
  10. } );
  11. })
  12. window.onload = () => {
  13. let div = document.createElement('div');
  14. div.innerHTML =
  15. `<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.10.0/styles/default.min.css">`;
  16. document.head.append(...div.children);
  17. }
  18. import Vue from 'vue'
  19. import VueRouter from 'vue-router'
  20. import Vuex from 'vuex'
  21. import axios from 'axios'
  22. import VueAxios from 'vue-axios'
  23. import linkExpander from './assets/js/linkExpander'
  24. import App from './App'
  25. import store from './store/index'
  26. const Index = () => import('./components/routes/Index')
  27. const P = () => import('./components/routes/P')
  28. const Start = () => import('./components/routes/Start')
  29. const Thread = () => import('./components/routes/Thread')
  30. const ThreadNew = () => import('./components/routes/ThreadNew')
  31. const Search = () => import('./components/routes/Search')
  32. const User = () => import('./components/routes/User')
  33. const UserPosts = () => import('./components/routes/UserPosts')
  34. const UserThreads = () => import('./components/routes/UserThreads')
  35. const Settings = () => import('./components/routes/Settings')
  36. const SettingsGeneral = () => import('./components/routes/SettingsGeneral')
  37. const SettingsAccount = () => import('./components/routes/SettingsAccount')
  38. const Admin = () => import('./components/routes/Admin')
  39. const AdminDashboard = () => import('./components/routes/AdminDashboard')
  40. const AdminModerationReports = () => import('./components/routes/AdminModerationReports')
  41. const AdminModerationBannedUsers = () => import('./components/routes/AdminModerationBannedUsers')
  42. const AdminGeneral = () => import('./components/routes/AdminGeneral')
  43. const AdminUsers = () => import('./components/routes/AdminUsers')
  44. import NotFound from './components/routes/NotFound'
  45. Vue.use(VueRouter)
  46. Vue.use(Vuex)
  47. Vue.use(VueAxios, axios)
  48. Vue.use(linkExpander)
  49. const router = new VueRouter({
  50. routes: [
  51. { path: '/', redirect: '/category/all' },
  52. { path: '/category/:category', component: Index },
  53. { path: '/p/:id', component: P },
  54. { path: '/start', component: Start },
  55. { path: '/thread/:slug/:id', component: Thread },
  56. { path: '/thread/:slug/:id/:post_number', name: 'thread-post', component: Thread },
  57. { path: '/thread/new', component: ThreadNew },
  58. { path: '/search/:q', component: Search },
  59. { path: '/user/:username', redirect: '/user/:username/posts', component: User, children: [
  60. { path: 'posts', component: UserPosts },
  61. { path: 'threads', component: UserThreads }
  62. ] },
  63. { path: '/settings', redirect: '/settings/general', component: Settings, children: [
  64. { path: 'general', component: SettingsGeneral },
  65. { path: 'account', component: SettingsAccount }
  66. ] },
  67. { path: '/admin', redirect: '/admin/dashboard', component: Admin, children: [
  68. { path: 'dashboard', component: AdminDashboard },
  69. { path: 'general', component: AdminGeneral },
  70. { path: 'users', component: AdminUsers },
  71. { path: 'moderation', redirect: '/admin/moderation/reports' },
  72. { path: 'moderation/reports', component: AdminModerationReports },
  73. { path: 'moderation/bans', component: AdminModerationBannedUsers }
  74. ] },
  75. { path: '*', component: NotFound }
  76. ],
  77. mode: 'history'
  78. })
  79. router.beforeEach((to, from, next) => {
  80. router.app.$store.commit('set404Page', false)
  81. //Do not change progress bar when scrolling through posts on a thread
  82. if(
  83. (to.name !== 'thread-post' && from.name !== 'thread-post') &&
  84. (!to.params.id || to.params.id !== from.params.id)
  85. ) {
  86. NProgress.start()
  87. }
  88. next()
  89. })
  90. router.afterEach(() => {
  91. NProgress.done()
  92. })
  93. Vue.filter('formatDate', function (value, format = '', join = ' ') {
  94. if(typeof value !== 'object') {
  95. value = new Date(value)
  96. }
  97. let sinceNow = new Date(new Date() - value)
  98. //Add leading zero if under 10
  99. function lz(num) {
  100. if(num < 10) {
  101. return '0' + num;
  102. } else {
  103. return '' + num;
  104. }
  105. }
  106. function p(word, num) {
  107. if(num === 1) {
  108. return word
  109. } else {
  110. return word + 's'
  111. }
  112. }
  113. //2 minutes
  114. if(sinceNow <= 1000*60*2) {
  115. return 'Just now'
  116. } else if(sinceNow <= 1000*60*60) {
  117. return sinceNow.getMinutes() + ' minutes ago'
  118. } else if(sinceNow <= 1000*60*60*24) {
  119. let hours = sinceNow.getHours()
  120. return hours + ' ' + p('hour', hours) + ' ago'
  121. } else if(sinceNow <= 1000*60*60*24*2) {
  122. let days = Math.floor(sinceNow / (1000*60*60*24))
  123. return days + ' ' + p('day', days) + ' ago at ' + value.toTimeString().slice(0, 5)
  124. } else {
  125. return (
  126. lz(value.getDate()) + '/' +
  127. lz(value.getMonth() + 1) + '/' +
  128. value.getUTCFullYear()
  129. );
  130. }
  131. });
  132. Vue.filter('stripTags', function (value) {
  133. let div = document.createElement('div')
  134. div.innerHTML = value
  135. return div.textContent
  136. });
  137. Vue.filter('truncate', function (value, length) {
  138. if(value.length <= length) {
  139. return value
  140. } else {
  141. return value.slice(0, length) + '...'
  142. }
  143. });
  144. Vue.filter('pluralize', function(number, value) {
  145. if(number === 1) {
  146. return value
  147. } else {
  148. return value + 's'
  149. }
  150. })
  151. let Root = new Vue({
  152. el: '#app',
  153. template: '<App/>',
  154. store,
  155. components: { App },
  156. router
  157. })
  158. let cookieDict = document.cookie
  159. .split(';')
  160. .map(a => a.split('=').map(a => a.trim()) )
  161. .map(a => {
  162. let k = a[0], v = a[1]
  163. return { [k] : v }
  164. })
  165. .reduce((combinedObj, o) => {
  166. let key = Object.keys(o)[0]
  167. combinedObj[key] = o[key]
  168. return combinedObj
  169. }, {})
  170. if(cookieDict.username) Root.$store.commit('setUsername', cookieDict.username)
  171. if(cookieDict.admin === 'false') {
  172. Root.$store.commit('setAdmin', false)
  173. } else if(cookieDict.admin === 'true') {
  174. Root.$store.commit('setAdmin', true)
  175. }