Merge branch 'develop' into feature/version-info
This commit is contained in:
		
						commit
						3c5c09c74f
					
				
					 31 changed files with 706 additions and 400 deletions
				
			
		|  | @ -8,6 +8,7 @@ import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_pan | ||||||
| import ChatPanel from './components/chat_panel/chat_panel.vue' | import ChatPanel from './components/chat_panel/chat_panel.vue' | ||||||
| import MediaModal from './components/media_modal/media_modal.vue' | import MediaModal from './components/media_modal/media_modal.vue' | ||||||
| import SideDrawer from './components/side_drawer/side_drawer.vue' | import SideDrawer from './components/side_drawer/side_drawer.vue' | ||||||
|  | import MobilePostStatusModal from './components/mobile_post_status_modal/mobile_post_status_modal.vue' | ||||||
| import { unseenNotificationsFromStore } from './services/notification_utils/notification_utils' | import { unseenNotificationsFromStore } from './services/notification_utils/notification_utils' | ||||||
| 
 | 
 | ||||||
| export default { | export default { | ||||||
|  | @ -22,7 +23,8 @@ export default { | ||||||
|     WhoToFollowPanel, |     WhoToFollowPanel, | ||||||
|     ChatPanel, |     ChatPanel, | ||||||
|     MediaModal, |     MediaModal, | ||||||
|     SideDrawer |     SideDrawer, | ||||||
|  |     MobilePostStatusModal | ||||||
|   }, |   }, | ||||||
|   data: () => ({ |   data: () => ({ | ||||||
|     mobileActivePanel: 'timeline', |     mobileActivePanel: 'timeline', | ||||||
|  |  | ||||||
							
								
								
									
										25
									
								
								src/App.scss
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								src/App.scss
									
									
									
									
									
								
							|  | @ -671,6 +671,31 @@ nav { | ||||||
|   border-radius: var(--inputRadius, $fallback--inputRadius); |   border-radius: var(--inputRadius, $fallback--inputRadius); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @keyframes modal-background-fadein { | ||||||
|  |   from { | ||||||
|  |     background-color: rgba(0, 0, 0, 0); | ||||||
|  |   } | ||||||
|  |   to { | ||||||
|  |     background-color: rgba(0, 0, 0, 0.5); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .modal-view { | ||||||
|  |   z-index: 1000; | ||||||
|  |   position: fixed; | ||||||
|  |   top: 0; | ||||||
|  |   left: 0; | ||||||
|  |   right: 0; | ||||||
|  |   bottom: 0; | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: center; | ||||||
|  |   align-items: center; | ||||||
|  |   overflow: auto; | ||||||
|  |   animation-duration: 0.2s; | ||||||
|  |   background-color: rgba(0, 0, 0, 0.5); | ||||||
|  |   animation-name: modal-background-fadein; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .button-icon { | .button-icon { | ||||||
|   font-size: 1.2em; |   font-size: 1.2em; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -50,6 +50,7 @@ | ||||||
|       <media-modal></media-modal> |       <media-modal></media-modal> | ||||||
|     </div> |     </div> | ||||||
|     <chat-panel :floating="true" v-if="currentUser && chat" class="floating-chat mobile-hidden"></chat-panel> |     <chat-panel :floating="true" v-if="currentUser && chat" class="floating-chat mobile-hidden"></chat-panel> | ||||||
|  |     <MobilePostStatusModal /> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,10 +4,11 @@ import routes from './routes' | ||||||
| 
 | 
 | ||||||
| import App from '../App.vue' | import App from '../App.vue' | ||||||
| 
 | 
 | ||||||
| const afterStoreSetup = ({ store, i18n }) => { | const getStatusnetConfig = async ({ store }) => { | ||||||
|   window.fetch('/api/statusnet/config.json') |   try { | ||||||
|     .then((res) => res.json()) |     const res = await window.fetch('/api/statusnet/config.json') | ||||||
|     .then((data) => { |     if (res.ok) { | ||||||
|  |       const data = await res.json() | ||||||
|       const { name, closed: registrationClosed, textlimit, uploadlimit, server, vapidPublicKey } = data.site |       const { name, closed: registrationClosed, textlimit, uploadlimit, server, vapidPublicKey } = data.site | ||||||
| 
 | 
 | ||||||
|       store.dispatch('setInstanceOption', { name: 'name', value: name }) |       store.dispatch('setInstanceOption', { name: 'name', value: name }) | ||||||
|  | @ -28,16 +29,32 @@ const afterStoreSetup = ({ store, i18n }) => { | ||||||
|         store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey }) |         store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey }) | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       var apiConfig = data.site.pleromafe |       return data.site.pleromafe | ||||||
|  |     } else { | ||||||
|  |       throw (res) | ||||||
|  |     } | ||||||
|  |   } catch (error) { | ||||||
|  |     console.error('Could not load statusnet config, potentially fatal') | ||||||
|  |     console.error(error) | ||||||
|  |   } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|       window.fetch('/static/config.json') | const getStaticConfig = async () => { | ||||||
|         .then((res) => res.json()) |   try { | ||||||
|         .catch((err) => { |     const res = await window.fetch('/static/config.json') | ||||||
|  |     if (res.ok) { | ||||||
|  |       return res.json() | ||||||
|  |     } else { | ||||||
|  |       throw (res) | ||||||
|  |     } | ||||||
|  |   } catch (error) { | ||||||
|     console.warn('Failed to load static/config.json, continuing without it.') |     console.warn('Failed to load static/config.json, continuing without it.') | ||||||
|           console.warn(err) |     console.warn(error) | ||||||
|     return {} |     return {} | ||||||
|         }) |   } | ||||||
|         .then((staticConfig) => { | } | ||||||
|  | 
 | ||||||
|  | const setSettings = async ({ apiConfig, staticConfig, store }) => { | ||||||
|   const overrides = window.___pleromafe_dev_overrides || {} |   const overrides = window.___pleromafe_dev_overrides || {} | ||||||
|   const env = window.___pleromafe_mode.NODE_ENV |   const env = window.___pleromafe_mode.NODE_ENV | ||||||
| 
 | 
 | ||||||
|  | @ -51,7 +68,7 @@ const afterStoreSetup = ({ store, i18n }) => { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   const copyInstanceOption = (name) => { |   const copyInstanceOption = (name) => { | ||||||
|             store.dispatch('setInstanceOption', {name, value: config[name]}) |     store.dispatch('setInstanceOption', { name, value: config[name] }) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   copyInstanceOption('nsfwCensorImage') |   copyInstanceOption('nsfwCensorImage') | ||||||
|  | @ -96,72 +113,83 @@ const afterStoreSetup = ({ store, i18n }) => { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return store.dispatch('setTheme', config['theme']) |   return store.dispatch('setTheme', config['theme']) | ||||||
|         }) | } | ||||||
|         .then(() => { |  | ||||||
|           const router = new VueRouter({ |  | ||||||
|             mode: 'history', |  | ||||||
|             routes: routes(store), |  | ||||||
|             scrollBehavior: (to, _from, savedPosition) => { |  | ||||||
|               if (to.matched.some(m => m.meta.dontScroll)) { |  | ||||||
|                 return false |  | ||||||
|               } |  | ||||||
|               return savedPosition || { x: 0, y: 0 } |  | ||||||
|             } |  | ||||||
|           }) |  | ||||||
| 
 | 
 | ||||||
|           /* eslint-disable no-new */ | const getTOS = async ({ store }) => { | ||||||
|           new Vue({ |   try { | ||||||
|             router, |     const res = await window.fetch('/static/terms-of-service.html') | ||||||
|             store, |     if (res.ok) { | ||||||
|             i18n, |       const html = await res.text() | ||||||
|             el: '#app', |  | ||||||
|             render: h => h(App) |  | ||||||
|           }) |  | ||||||
|         }) |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|   window.fetch('/static/terms-of-service.html') |  | ||||||
|     .then((res) => res.text()) |  | ||||||
|     .then((html) => { |  | ||||||
|       store.dispatch('setInstanceOption', { name: 'tos', value: html }) |       store.dispatch('setInstanceOption', { name: 'tos', value: html }) | ||||||
|     }) |     } else { | ||||||
|  |       throw (res) | ||||||
|  |     } | ||||||
|  |   } catch (e) { | ||||||
|  |     console.warn("Can't load TOS") | ||||||
|  |     console.warn(e) | ||||||
|  |   } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|   window.fetch('/api/pleroma/emoji.json') | const getInstancePanel = async ({ store }) => { | ||||||
|     .then( |   try { | ||||||
|       (res) => res.json() |     const res = await window.fetch('/instance/panel.html') | ||||||
|         .then( |     if (res.ok) { | ||||||
|           (values) => { |       const html = await res.text() | ||||||
|  |       store.dispatch('setInstanceOption', { name: 'instanceSpecificPanelContent', value: html }) | ||||||
|  |     } else { | ||||||
|  |       throw (res) | ||||||
|  |     } | ||||||
|  |   } catch (e) { | ||||||
|  |     console.warn("Can't load instance panel") | ||||||
|  |     console.warn(e) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const getStaticEmoji = async ({ store }) => { | ||||||
|  |   try { | ||||||
|  |     const res = await window.fetch('/static/emoji.json') | ||||||
|  |     if (res.ok) { | ||||||
|  |       const values = await res.json() | ||||||
|  |       const emoji = Object.keys(values).map((key) => { | ||||||
|  |         return { shortcode: key, image_url: false, 'utf': values[key] } | ||||||
|  |       }) | ||||||
|  |       store.dispatch('setInstanceOption', { name: 'emoji', value: emoji }) | ||||||
|  |     } else { | ||||||
|  |       throw (res) | ||||||
|  |     } | ||||||
|  |   } catch (e) { | ||||||
|  |     console.warn("Can't load static emoji") | ||||||
|  |     console.warn(e) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // This is also used to indicate if we have a 'pleroma backend' or not.
 | ||||||
|  | // Somewhat weird, should probably be somewhere else.
 | ||||||
|  | const getCustomEmoji = async ({ store }) => { | ||||||
|  |   try { | ||||||
|  |     const res = await window.fetch('/api/pleroma/emoji.json') | ||||||
|  |     if (res.ok) { | ||||||
|  |       const values = await res.json() | ||||||
|       const emoji = Object.keys(values).map((key) => { |       const emoji = Object.keys(values).map((key) => { | ||||||
|         return { shortcode: key, image_url: values[key] } |         return { shortcode: key, image_url: values[key] } | ||||||
|       }) |       }) | ||||||
|       store.dispatch('setInstanceOption', { name: 'customEmoji', value: emoji }) |       store.dispatch('setInstanceOption', { name: 'customEmoji', value: emoji }) | ||||||
|       store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: true }) |       store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: true }) | ||||||
|           }, |     } else { | ||||||
|           (failure) => { |       throw (res) | ||||||
|             store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: false }) |  | ||||||
|     } |     } | ||||||
|         ), |   } catch (e) { | ||||||
|       (error) => console.log(error) |     store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: false }) | ||||||
|     ) |     console.warn("Can't load custom emojis, maybe not a Pleroma instance?") | ||||||
|  |     console.warn(e) | ||||||
|  |   } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|   window.fetch('/static/emoji.json') | const getNodeInfo = async ({ store }) => { | ||||||
|     .then((res) => res.json()) |   try { | ||||||
|     .then((values) => { |     const res = await window.fetch('/nodeinfo/2.0.json') | ||||||
|       const emoji = Object.keys(values).map((key) => { |     if (res.ok) { | ||||||
|         return { shortcode: key, image_url: false, 'utf': values[key] } |       const data = await res.json() | ||||||
|       }) |  | ||||||
|       store.dispatch('setInstanceOption', { name: 'emoji', value: emoji }) |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|   window.fetch('/instance/panel.html') |  | ||||||
|     .then((res) => res.text()) |  | ||||||
|     .then((html) => { |  | ||||||
|       store.dispatch('setInstanceOption', { name: 'instanceSpecificPanelContent', value: html }) |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|   window.fetch('/nodeinfo/2.0.json') |  | ||||||
|     .then((res) => res.json()) |  | ||||||
|     .then((data) => { |  | ||||||
|       const metadata = data.metadata |       const metadata = data.metadata | ||||||
| 
 | 
 | ||||||
|       const features = metadata.features |       const features = metadata.features | ||||||
|  | @ -169,8 +197,6 @@ const afterStoreSetup = ({ store, i18n }) => { | ||||||
|       store.dispatch('setInstanceOption', { name: 'chatAvailable', value: features.includes('chat') }) |       store.dispatch('setInstanceOption', { name: 'chatAvailable', value: features.includes('chat') }) | ||||||
|       store.dispatch('setInstanceOption', { name: 'gopherAvailable', value: features.includes('gopher') }) |       store.dispatch('setInstanceOption', { name: 'gopherAvailable', value: features.includes('gopher') }) | ||||||
| 
 | 
 | ||||||
|       store.dispatch('setInstanceOption', { name: 'postFormats', value: metadata.postFormats }) |  | ||||||
| 
 |  | ||||||
|       store.dispatch('setInstanceOption', { name: 'restrictedNicknames', value: metadata.restrictedNicknames }) |       store.dispatch('setInstanceOption', { name: 'restrictedNicknames', value: metadata.restrictedNicknames }) | ||||||
| 
 | 
 | ||||||
|       const suggestions = metadata.suggestions |       const suggestions = metadata.suggestions | ||||||
|  | @ -182,6 +208,48 @@ const afterStoreSetup = ({ store, i18n }) => { | ||||||
| 
 | 
 | ||||||
|       const frontendVersion = window.___pleromafe_commit_hash |       const frontendVersion = window.___pleromafe_commit_hash | ||||||
|       store.dispatch('setInstanceOption', { name: 'frontendVersion', value: frontendVersion }) |       store.dispatch('setInstanceOption', { name: 'frontendVersion', value: frontendVersion }) | ||||||
|  |     } else { | ||||||
|  |       throw (res) | ||||||
|  |     } | ||||||
|  |   } catch (e) { | ||||||
|  |     console.warn('Could not load nodeinfo') | ||||||
|  |     console.warn(e) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const afterStoreSetup = async ({ store, i18n }) => { | ||||||
|  |   const apiConfig = await getStatusnetConfig({ store }) | ||||||
|  |   const staticConfig = await getStaticConfig() | ||||||
|  |   await setSettings({ store, apiConfig, staticConfig }) | ||||||
|  |   await getTOS({ store }) | ||||||
|  |   await getInstancePanel({ store }) | ||||||
|  |   await getStaticEmoji({ store }) | ||||||
|  |   await getCustomEmoji({ store }) | ||||||
|  |   await getNodeInfo({ store }) | ||||||
|  | 
 | ||||||
|  |   // Now we have the server settings and can try logging in
 | ||||||
|  |   if (store.state.oauth.token) { | ||||||
|  |     store.dispatch('loginUser', store.state.oauth.token) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const router = new VueRouter({ | ||||||
|  |     mode: 'history', | ||||||
|  |     routes: routes(store), | ||||||
|  |     scrollBehavior: (to, _from, savedPosition) => { | ||||||
|  |       if (to.matched.some(m => m.meta.dontScroll)) { | ||||||
|  |         return false | ||||||
|  |       } | ||||||
|  |       return savedPosition || { x: 0, y: 0 } | ||||||
|  |     } | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   /* eslint-disable no-new */ | ||||||
|  |   return new Vue({ | ||||||
|  |     router, | ||||||
|  |     store, | ||||||
|  |     i18n, | ||||||
|  |     el: '#app', | ||||||
|  |     render: h => h(App) | ||||||
|   }) |   }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -13,7 +13,6 @@ import FollowRequests from 'components/follow_requests/follow_requests.vue' | ||||||
| import OAuthCallback from 'components/oauth_callback/oauth_callback.vue' | import OAuthCallback from 'components/oauth_callback/oauth_callback.vue' | ||||||
| import UserSearch from 'components/user_search/user_search.vue' | import UserSearch from 'components/user_search/user_search.vue' | ||||||
| import Notifications from 'components/notifications/notifications.vue' | import Notifications from 'components/notifications/notifications.vue' | ||||||
| import UserPanel from 'components/user_panel/user_panel.vue' |  | ||||||
| import LoginForm from 'components/login_form/login_form.vue' | import LoginForm from 'components/login_form/login_form.vue' | ||||||
| import ChatPanel from 'components/chat_panel/chat_panel.vue' | import ChatPanel from 'components/chat_panel/chat_panel.vue' | ||||||
| import WhoToFollow from 'components/who_to_follow/who_to_follow.vue' | import WhoToFollow from 'components/who_to_follow/who_to_follow.vue' | ||||||
|  | @ -43,7 +42,6 @@ export default (store) => { | ||||||
|     { name: 'friend-requests', path: '/friend-requests', component: FollowRequests }, |     { name: 'friend-requests', path: '/friend-requests', component: FollowRequests }, | ||||||
|     { name: 'user-settings', path: '/user-settings', component: UserSettings }, |     { name: 'user-settings', path: '/user-settings', component: UserSettings }, | ||||||
|     { name: 'notifications', path: '/:username/notifications', component: Notifications }, |     { name: 'notifications', path: '/:username/notifications', component: Notifications }, | ||||||
|     { name: 'new-status', path: '/:username/new-status', component: UserPanel }, |  | ||||||
|     { name: 'login', path: '/login', component: LoginForm }, |     { name: 'login', path: '/login', component: LoginForm }, | ||||||
|     { name: 'chat', path: '/chat', component: ChatPanel, props: () => ({ floating: false }) }, |     { name: 'chat', path: '/chat', component: ChatPanel, props: () => ({ floating: false }) }, | ||||||
|     { name: 'oauth-callback', path: '/oauth-callback', component: OAuthCallback, props: (route) => ({ code: route.query.code }) }, |     { name: 'oauth-callback', path: '/oauth-callback', component: OAuthCallback, props: (route) => ({ code: route.query.code }) }, | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| <template> | <template> | ||||||
|   <div class="modal-view" v-if="showing" @click.prevent="hide"> |   <div class="modal-view media-modal-view" v-if="showing" @click.prevent="hide"> | ||||||
|     <img class="modal-image" v-if="type === 'image'" :src="currentMedia.url"></img> |     <img class="modal-image" v-if="type === 'image'" :src="currentMedia.url"></img> | ||||||
|     <VideoAttachment |     <VideoAttachment | ||||||
|       class="modal-image" |       class="modal-image" | ||||||
|  | @ -32,18 +32,7 @@ | ||||||
| <style lang="scss"> | <style lang="scss"> | ||||||
| @import '../../_variables.scss'; | @import '../../_variables.scss'; | ||||||
| 
 | 
 | ||||||
| .modal-view { | .media-modal-view { | ||||||
|   z-index: 1000; |  | ||||||
|   position: fixed; |  | ||||||
|   top: 0; |  | ||||||
|   left: 0; |  | ||||||
|   right: 0; |  | ||||||
|   bottom: 0; |  | ||||||
|   display: flex; |  | ||||||
|   justify-content: center; |  | ||||||
|   align-items: center; |  | ||||||
|   background-color: rgba(0, 0, 0, 0.5); |  | ||||||
| 
 |  | ||||||
|   &:hover { |   &:hover { | ||||||
|     .modal-view-button-arrow { |     .modal-view-button-arrow { | ||||||
|       opacity: 0.75; |       opacity: 0.75; | ||||||
|  |  | ||||||
|  | @ -0,0 +1,91 @@ | ||||||
|  | import PostStatusForm from '../post_status_form/post_status_form.vue' | ||||||
|  | import { throttle } from 'lodash' | ||||||
|  | 
 | ||||||
|  | const MobilePostStatusModal = { | ||||||
|  |   components: { | ||||||
|  |     PostStatusForm | ||||||
|  |   }, | ||||||
|  |   data () { | ||||||
|  |     return { | ||||||
|  |       hidden: false, | ||||||
|  |       postFormOpen: false, | ||||||
|  |       scrollingDown: false, | ||||||
|  |       inputActive: false, | ||||||
|  |       oldScrollPos: 0, | ||||||
|  |       amountScrolled: 0 | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   created () { | ||||||
|  |     window.addEventListener('scroll', this.handleScroll) | ||||||
|  |     window.addEventListener('resize', this.handleOSK) | ||||||
|  |   }, | ||||||
|  |   destroyed () { | ||||||
|  |     window.removeEventListener('scroll', this.handleScroll) | ||||||
|  |     window.removeEventListener('resize', this.handleOSK) | ||||||
|  |   }, | ||||||
|  |   computed: { | ||||||
|  |     currentUser () { | ||||||
|  |       return this.$store.state.users.currentUser | ||||||
|  |     }, | ||||||
|  |     isHidden () { | ||||||
|  |       return this.hidden || this.inputActive | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   methods: { | ||||||
|  |     openPostForm () { | ||||||
|  |       this.postFormOpen = true | ||||||
|  |       this.hidden = true | ||||||
|  | 
 | ||||||
|  |       const el = this.$el.querySelector('textarea') | ||||||
|  |       this.$nextTick(function () { | ||||||
|  |         el.focus() | ||||||
|  |       }) | ||||||
|  |     }, | ||||||
|  |     closePostForm () { | ||||||
|  |       this.postFormOpen = false | ||||||
|  |       this.hidden = false | ||||||
|  |     }, | ||||||
|  |     handleOSK () { | ||||||
|  |       // This is a big hack: we're guessing from changed window sizes if the
 | ||||||
|  |       // on-screen keyboard is active or not. This is only really important
 | ||||||
|  |       // for phones in portrait mode and it's more important to show the button
 | ||||||
|  |       // in normal scenarios on all phones, than it is to hide it when the
 | ||||||
|  |       // keyboard is active.
 | ||||||
|  |       // Guesswork based on https://www.mydevice.io/#compare-devices
 | ||||||
|  | 
 | ||||||
|  |       // for example, iphone 4 and android phones from the same time period
 | ||||||
|  |       const smallPhone = window.innerWidth < 350 | ||||||
|  |       const smallPhoneKbOpen = smallPhone && window.innerHeight < 345 | ||||||
|  | 
 | ||||||
|  |       const biggerPhone = !smallPhone && window.innerWidth < 450 | ||||||
|  |       const biggerPhoneKbOpen = biggerPhone && window.innerHeight < 560 | ||||||
|  |       if (smallPhoneKbOpen || biggerPhoneKbOpen) { | ||||||
|  |         this.inputActive = true | ||||||
|  |       } else { | ||||||
|  |         this.inputActive = false | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     handleScroll: throttle(function () { | ||||||
|  |       const scrollAmount = window.scrollY - this.oldScrollPos | ||||||
|  |       const scrollingDown = scrollAmount > 0 | ||||||
|  | 
 | ||||||
|  |       if (scrollingDown !== this.scrollingDown) { | ||||||
|  |         this.amountScrolled = 0 | ||||||
|  |         this.scrollingDown = scrollingDown | ||||||
|  |         if (!scrollingDown) { | ||||||
|  |           this.hidden = false | ||||||
|  |         } | ||||||
|  |       } else if (scrollingDown) { | ||||||
|  |         this.amountScrolled += scrollAmount | ||||||
|  |         if (this.amountScrolled > 100 && !this.hidden) { | ||||||
|  |           this.hidden = true | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       this.oldScrollPos = window.scrollY | ||||||
|  |       this.scrollingDown = scrollingDown | ||||||
|  |     }, 100) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export default MobilePostStatusModal | ||||||
|  | @ -0,0 +1,76 @@ | ||||||
|  | <template> | ||||||
|  | <div v-if="currentUser"> | ||||||
|  |   <div | ||||||
|  |     class="post-form-modal-view modal-view" | ||||||
|  |     v-show="postFormOpen" | ||||||
|  |     @click="closePostForm" | ||||||
|  |   > | ||||||
|  |     <div class="post-form-modal-panel panel" @click.stop=""> | ||||||
|  |       <div class="panel-heading">{{$t('post_status.new_status')}}</div> | ||||||
|  |       <PostStatusForm class="panel-body" @posted="closePostForm"/> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  |   <button | ||||||
|  |     class="new-status-button" | ||||||
|  |     :class="{ 'hidden': isHidden }" | ||||||
|  |     @click="openPostForm" | ||||||
|  |   > | ||||||
|  |     <i class="icon-edit" /> | ||||||
|  |   </button> | ||||||
|  | </div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script src="./mobile_post_status_modal.js"></script> | ||||||
|  | 
 | ||||||
|  | <style lang="scss"> | ||||||
|  | @import '../../_variables.scss'; | ||||||
|  | 
 | ||||||
|  | .post-form-modal-view { | ||||||
|  |   max-height: 100%; | ||||||
|  |   display: block; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .post-form-modal-panel { | ||||||
|  |   flex-shrink: 0; | ||||||
|  |   margin: 25% 0 4em 0; | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .new-status-button { | ||||||
|  |   width: 5em; | ||||||
|  |   height: 5em; | ||||||
|  |   border-radius: 100%; | ||||||
|  |   position: fixed; | ||||||
|  |   bottom: 1.5em; | ||||||
|  |   right: 1.5em; | ||||||
|  |   // TODO: this needs its own color, it has to stand out enough and link color | ||||||
|  |   // is not very optimal for this particular use. | ||||||
|  |   background-color: $fallback--fg; | ||||||
|  |   background-color: var(--btn, $fallback--fg); | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: center; | ||||||
|  |   align-items: center; | ||||||
|  |   box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3), 0px 4px 6px rgba(0, 0, 0, 0.3); | ||||||
|  |   z-index: 10; | ||||||
|  | 
 | ||||||
|  |   transition: 0.35s transform; | ||||||
|  |   transition-timing-function: cubic-bezier(0, 1, 0.5, 1); | ||||||
|  | 
 | ||||||
|  |   &.hidden { | ||||||
|  |     transform: translateY(150%); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   i { | ||||||
|  |     font-size: 1.5em; | ||||||
|  |     color: $fallback--text; | ||||||
|  |     color: var(--text, $fallback--text); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @media all and (min-width: 801px) { | ||||||
|  |   .new-status-button { | ||||||
|  |     display: none; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | </style> | ||||||
|  | @ -15,12 +15,7 @@ | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|       <ul> |       <ul> | ||||||
|         <li v-if="currentUser" @click="toggleDrawer"> |         <li v-if="!currentUser" @click="toggleDrawer"> | ||||||
|           <router-link :to="{ name: 'new-status', params: { username: currentUser.screen_name } }"> |  | ||||||
|             {{ $t("post_status.new_status") }} |  | ||||||
|           </router-link> |  | ||||||
|         </li> |  | ||||||
|         <li v-else @click="toggleDrawer"> |  | ||||||
|           <router-link :to="{ name: 'login' }"> |           <router-link :to="{ name: 'login' }"> | ||||||
|             {{ $t("login.login") }} |             {{ $t("login.login") }} | ||||||
|           </router-link> |           </router-link> | ||||||
|  | @ -119,14 +114,14 @@ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .side-drawer-container-open { | .side-drawer-container-open { | ||||||
|   transition-delay: 0.0s; |   transition: 0.35s; | ||||||
|   transition-property: left; |   transition-property: background-color; | ||||||
|  |   background-color: rgba(0, 0, 0, 0.5); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .side-drawer-container-closed { | .side-drawer-container-closed { | ||||||
|   left: -100%; |   left: -100%; | ||||||
|   transition-delay: 0.5s; |   background-color: rgba(0, 0, 0, 0); | ||||||
|   transition-property: left; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .side-drawer-click-outside { | .side-drawer-click-outside { | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ | ||||||
|             <div :title="user.name" class='user-name' v-if="user.name_html" v-html="user.name_html"></div> |             <div :title="user.name" class='user-name' v-if="user.name_html" v-html="user.name_html"></div> | ||||||
|             <div :title="user.name" class='user-name' v-else>{{user.name}}</div> |             <div :title="user.name" class='user-name' v-else>{{user.name}}</div> | ||||||
|             <router-link :to="{ name: 'user-settings' }" v-if="!isOtherUser"> |             <router-link :to="{ name: 'user-settings' }" v-if="!isOtherUser"> | ||||||
|               <i class="button-icon icon-cog usersettings" :title="$t('tool_tip.user_settings')"></i> |               <i class="button-icon icon-pencil usersettings" :title="$t('tool_tip.user_settings')"></i> | ||||||
|             </router-link> |             </router-link> | ||||||
|             <a :href="user.statusnet_profile_url" target="_blank" v-if="isOtherUser && !user.is_local"> |             <a :href="user.statusnet_profile_url" target="_blank" v-if="isOtherUser && !user.is_local"> | ||||||
|               <i class="icon-link-ext usersettings"></i> |               <i class="icon-link-ext usersettings"></i> | ||||||
|  | @ -159,6 +159,18 @@ | ||||||
| 
 | 
 | ||||||
|   &-bio { |   &-bio { | ||||||
|     text-align: center; |     text-align: center; | ||||||
|  | 
 | ||||||
|  |     img { | ||||||
|  |       object-fit: contain; | ||||||
|  |       vertical-align: middle; | ||||||
|  |       max-width: 100%; | ||||||
|  |       max-height: 400px; | ||||||
|  | 
 | ||||||
|  |       .emoji { | ||||||
|  |         width: 32px; | ||||||
|  |         height: 32px; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // Modifiers |   // Modifiers | ||||||
|  |  | ||||||
|  | @ -71,7 +71,9 @@ | ||||||
|     "account_not_locked_warning_link": "uzamčen", |     "account_not_locked_warning_link": "uzamčen", | ||||||
|     "attachments_sensitive": "Označovat přílohy jako citlivé", |     "attachments_sensitive": "Označovat přílohy jako citlivé", | ||||||
|     "content_type": { |     "content_type": { | ||||||
|       "plain_text": "Prostý text" |       "plain_text": "Prostý text", | ||||||
|  |       "text/html": "HTML", | ||||||
|  |       "text/markdown": "Markdown" | ||||||
|     }, |     }, | ||||||
|     "content_warning": "Předmět (volitelný)", |     "content_warning": "Předmět (volitelný)", | ||||||
|     "default": "Právě jsem přistál v L.A.", |     "default": "Právě jsem přistál v L.A.", | ||||||
|  | @ -95,7 +97,7 @@ | ||||||
|     "new_captcha": "Kliknutím na obrázek získáte novou CAPTCHA", |     "new_captcha": "Kliknutím na obrázek získáte novou CAPTCHA", | ||||||
|     "username_placeholder": "např. lain", |     "username_placeholder": "např. lain", | ||||||
|     "fullname_placeholder": "např. Lain Iwakura", |     "fullname_placeholder": "např. Lain Iwakura", | ||||||
|     "bio_placeholder": "např.\nNazdar, jsem Lain\nJsem anime dívka a žiji v příměstském Japonsku. Možná mě znáte z Wired.", |     "bio_placeholder": "např.\nNazdar, jsem Lain\nJsem anime dívka žijící v příměstském Japonsku. Možná mě znáte z Wired.", | ||||||
|     "validations": { |     "validations": { | ||||||
|       "username_required": "nemůže být prázdné", |       "username_required": "nemůže být prázdné", | ||||||
|       "fullname_required": "nemůže být prázdné", |       "fullname_required": "nemůže být prázdné", | ||||||
|  | @ -204,7 +206,7 @@ | ||||||
|     "radii_help": "Nastavit zakulacení rohů rozhraní (v pixelech)", |     "radii_help": "Nastavit zakulacení rohů rozhraní (v pixelech)", | ||||||
|     "replies_in_timeline": "Odpovědi v časové ose", |     "replies_in_timeline": "Odpovědi v časové ose", | ||||||
|     "reply_link_preview": "Povolit náhledy odkazu pro odpověď při přejetí myši", |     "reply_link_preview": "Povolit náhledy odkazu pro odpověď při přejetí myši", | ||||||
|     "reply_visibility_all": "Zobrazit všechny odpovědiShow all replies", |     "reply_visibility_all": "Zobrazit všechny odpovědi", | ||||||
|     "reply_visibility_following": "Zobrazit pouze odpovědi směřované na mě nebo uživatele, které sleduji", |     "reply_visibility_following": "Zobrazit pouze odpovědi směřované na mě nebo uživatele, které sleduji", | ||||||
|     "reply_visibility_self": "Zobrazit pouze odpovědi směřované na mě", |     "reply_visibility_self": "Zobrazit pouze odpovědi směřované na mě", | ||||||
|     "saving_err": "Chyba při ukládání nastavení", |     "saving_err": "Chyba při ukládání nastavení", | ||||||
|  | @ -221,7 +223,6 @@ | ||||||
|     "subject_line_mastodon": "Jako u Mastodonu: zkopírovat tak, jak je", |     "subject_line_mastodon": "Jako u Mastodonu: zkopírovat tak, jak je", | ||||||
|     "subject_line_noop": "Nekopírovat", |     "subject_line_noop": "Nekopírovat", | ||||||
|     "post_status_content_type": "Publikovat typ obsahu příspěvku", |     "post_status_content_type": "Publikovat typ obsahu příspěvku", | ||||||
|     "status_content_type_plain": "Prostý text", |  | ||||||
|     "stop_gifs": "Přehrávat GIFy při přejetí myši", |     "stop_gifs": "Přehrávat GIFy při přejetí myši", | ||||||
|     "streaming": "Povolit automatické streamování nových příspěvků při rolování nahoru", |     "streaming": "Povolit automatické streamování nových příspěvků při rolování nahoru", | ||||||
|     "text": "Text", |     "text": "Text", | ||||||
|  | @ -339,7 +340,7 @@ | ||||||
|         "button": "Tlačítko", |         "button": "Tlačítko", | ||||||
|         "text": "Spousta dalšího {0} a {1}", |         "text": "Spousta dalšího {0} a {1}", | ||||||
|         "mono": "obsahu", |         "mono": "obsahu", | ||||||
|         "input": "Just landed in L.A.", |         "input": "Právě jsem přistál v L.A.", | ||||||
|         "faint_link": "pomocný manuál", |         "faint_link": "pomocný manuál", | ||||||
|         "fine_print": "Přečtěte si náš {0} a nenaučte se nic užitečného!", |         "fine_print": "Přečtěte si náš {0} a nenaučte se nic užitečného!", | ||||||
|         "header_faint": "Tohle je v pohodě", |         "header_faint": "Tohle je v pohodě", | ||||||
|  | @ -361,7 +362,7 @@ | ||||||
|     "no_statuses": "Žádné příspěvky" |     "no_statuses": "Žádné příspěvky" | ||||||
|   }, |   }, | ||||||
|   "status": { |   "status": { | ||||||
|     "reply_to": "Odpovědět uživateli", |     "reply_to": "Odpověď uživateli", | ||||||
|     "replies_list": "Odpovědi:" |     "replies_list": "Odpovědi:" | ||||||
|   }, |   }, | ||||||
| 
 | 
 | ||||||
|  | @ -413,7 +414,7 @@ | ||||||
|   "upload":{ |   "upload":{ | ||||||
|     "error": { |     "error": { | ||||||
|       "base": "Nahrávání selhalo.", |       "base": "Nahrávání selhalo.", | ||||||
|       "file_too_big": "Soubor je úříliš velký [{filesize}{filesizeunit} / {allowedsize}{allowedsizeunit}]", |       "file_too_big": "Soubor je příliš velký [{filesize}{filesizeunit} / {allowedsize}{allowedsizeunit}]", | ||||||
|       "default": "Zkuste to znovu později" |       "default": "Zkuste to znovu později" | ||||||
|     }, |     }, | ||||||
|     "file_size_units": { |     "file_size_units": { | ||||||
|  |  | ||||||
|  | @ -53,9 +53,10 @@ const persistedStateOptions = { | ||||||
|     'users.lastLoginName', |     'users.lastLoginName', | ||||||
|     'oauth' |     'oauth' | ||||||
|   ] |   ] | ||||||
| } | }; | ||||||
| 
 | 
 | ||||||
| createPersistedState(persistedStateOptions).then((persistedState) => { | (async () => { | ||||||
|  |   const persistedState = await createPersistedState(persistedStateOptions) | ||||||
|   const store = new Vuex.Store({ |   const store = new Vuex.Store({ | ||||||
|     modules: { |     modules: { | ||||||
|       interface: interfaceModule, |       interface: interfaceModule, | ||||||
|  | @ -75,7 +76,7 @@ createPersistedState(persistedStateOptions).then((persistedState) => { | ||||||
|   }) |   }) | ||||||
| 
 | 
 | ||||||
|   afterStoreSetup({ store, i18n }) |   afterStoreSetup({ store, i18n }) | ||||||
| }) | })() | ||||||
| 
 | 
 | ||||||
| // These are inlined by webpack's DefinePlugin
 | // These are inlined by webpack's DefinePlugin
 | ||||||
| /* eslint-disable */ | /* eslint-disable */ | ||||||
|  |  | ||||||
|  | @ -1,12 +1,16 @@ | ||||||
| const chat = { | const chat = { | ||||||
|   state: { |   state: { | ||||||
|     messages: [], |     messages: [], | ||||||
|     channel: {state: ''} |     channel: {state: ''}, | ||||||
|  |     socket: null | ||||||
|   }, |   }, | ||||||
|   mutations: { |   mutations: { | ||||||
|     setChannel (state, channel) { |     setChannel (state, channel) { | ||||||
|       state.channel = channel |       state.channel = channel | ||||||
|     }, |     }, | ||||||
|  |     setSocket (state, socket) { | ||||||
|  |       state.socket = socket | ||||||
|  |     }, | ||||||
|     addMessage (state, message) { |     addMessage (state, message) { | ||||||
|       state.messages.push(message) |       state.messages.push(message) | ||||||
|       state.messages = state.messages.slice(-19, 20) |       state.messages = state.messages.slice(-19, 20) | ||||||
|  | @ -16,8 +20,12 @@ const chat = { | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   actions: { |   actions: { | ||||||
|  |     disconnectFromChat (store) { | ||||||
|  |       store.state.socket.disconnect() | ||||||
|  |     }, | ||||||
|     initializeChat (store, socket) { |     initializeChat (store, socket) { | ||||||
|       const channel = socket.channel('chat:public') |       const channel = socket.channel('chat:public') | ||||||
|  |       store.commit('setSocket', socket) | ||||||
|       channel.on('new_msg', (msg) => { |       channel.on('new_msg', (msg) => { | ||||||
|         store.commit('addMessage', msg) |         store.commit('addMessage', msg) | ||||||
|       }) |       }) | ||||||
|  |  | ||||||
|  | @ -333,6 +333,7 @@ export const mutations = { | ||||||
|     oldTimeline.newStatusCount = 0 |     oldTimeline.newStatusCount = 0 | ||||||
|     oldTimeline.visibleStatuses = slice(oldTimeline.statuses, 0, 50) |     oldTimeline.visibleStatuses = slice(oldTimeline.statuses, 0, 50) | ||||||
|     oldTimeline.minVisibleId = last(oldTimeline.visibleStatuses).id |     oldTimeline.minVisibleId = last(oldTimeline.visibleStatuses).id | ||||||
|  |     oldTimeline.minId = oldTimeline.minVisibleId | ||||||
|     oldTimeline.visibleStatusesObject = {} |     oldTimeline.visibleStatusesObject = {} | ||||||
|     each(oldTimeline.visibleStatuses, (status) => { oldTimeline.visibleStatusesObject[status.id] = status }) |     each(oldTimeline.visibleStatuses, (status) => { oldTimeline.visibleStatusesObject[status.id] = status }) | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|  | @ -292,6 +292,7 @@ const users = { | ||||||
| 
 | 
 | ||||||
|     logout (store) { |     logout (store) { | ||||||
|       store.commit('clearCurrentUser') |       store.commit('clearCurrentUser') | ||||||
|  |       store.dispatch('disconnectFromChat') | ||||||
|       store.commit('setToken', false) |       store.commit('setToken', false) | ||||||
|       store.dispatch('stopFetching', 'friends') |       store.dispatch('stopFetching', 'friends') | ||||||
|       store.commit('setBackendInteractor', backendInteractorService()) |       store.commit('setBackendInteractor', backendInteractorService()) | ||||||
|  | @ -321,6 +322,9 @@ const users = { | ||||||
| 
 | 
 | ||||||
|               if (user.token) { |               if (user.token) { | ||||||
|                 store.dispatch('setWsToken', user.token) |                 store.dispatch('setWsToken', user.token) | ||||||
|  | 
 | ||||||
|  |                 // Initialize the chat socket.
 | ||||||
|  |                 store.dispatch('initializeSocket') | ||||||
|               } |               } | ||||||
| 
 | 
 | ||||||
|               // Start getting fresh posts.
 |               // Start getting fresh posts.
 | ||||||
|  |  | ||||||
							
								
								
									
										0
									
								
								static/font/LICENSE.txt
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								static/font/LICENSE.txt
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								static/font/README.txt
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								static/font/README.txt
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										6
									
								
								static/font/config.json
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										6
									
								
								static/font/config.json
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							|  | @ -233,6 +233,12 @@ | ||||||
|       "css": "play-circled", |       "css": "play-circled", | ||||||
|       "code": 61764, |       "code": 61764, | ||||||
|       "src": "fontawesome" |       "src": "fontawesome" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "uid": "d35a1d35efeb784d1dc9ac18b9b6c2b6", | ||||||
|  |       "css": "pencil", | ||||||
|  |       "code": 59416, | ||||||
|  |       "src": "fontawesome" | ||||||
|     } |     } | ||||||
|   ] |   ] | ||||||
| } | } | ||||||
							
								
								
									
										0
									
								
								static/font/css/animation.css
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								static/font/css/animation.css
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										1
									
								
								static/font/css/fontello-codes.css
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										1
									
								
								static/font/css/fontello-codes.css
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							|  | @ -23,6 +23,7 @@ | ||||||
| .icon-plus:before { content: '\e815'; } /* '' */ | .icon-plus:before { content: '\e815'; } /* '' */ | ||||||
| .icon-adjust:before { content: '\e816'; } /* '' */ | .icon-adjust:before { content: '\e816'; } /* '' */ | ||||||
| .icon-edit:before { content: '\e817'; } /* '' */ | .icon-edit:before { content: '\e817'; } /* '' */ | ||||||
|  | .icon-pencil:before { content: '\e818'; } /* '' */ | ||||||
| .icon-spin3:before { content: '\e832'; } /* '' */ | .icon-spin3:before { content: '\e832'; } /* '' */ | ||||||
| .icon-spin4:before { content: '\e834'; } /* '' */ | .icon-spin4:before { content: '\e834'; } /* '' */ | ||||||
| .icon-link-ext:before { content: '\f08e'; } /* '' */ | .icon-link-ext:before { content: '\f08e'; } /* '' */ | ||||||
|  |  | ||||||
							
								
								
									
										13
									
								
								static/font/css/fontello-embedded.css
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										13
									
								
								static/font/css/fontello-embedded.css
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								static/font/css/fontello-ie7-codes.css
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										1
									
								
								static/font/css/fontello-ie7-codes.css
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							|  | @ -23,6 +23,7 @@ | ||||||
| .icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | .icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | ||||||
| .icon-adjust { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | .icon-adjust { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | ||||||
| .icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | .icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | ||||||
|  | .icon-pencil { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | ||||||
| .icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | .icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | ||||||
| .icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | .icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | ||||||
| .icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | .icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								static/font/css/fontello-ie7.css
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										1
									
								
								static/font/css/fontello-ie7.css
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							|  | @ -34,6 +34,7 @@ | ||||||
| .icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | .icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | ||||||
| .icon-adjust { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | .icon-adjust { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | ||||||
| .icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | .icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | ||||||
|  | .icon-pencil { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | ||||||
| .icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | .icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | ||||||
| .icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | .icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | ||||||
| .icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | .icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } | ||||||
|  |  | ||||||
							
								
								
									
										15
									
								
								static/font/css/fontello.css
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										15
									
								
								static/font/css/fontello.css
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							|  | @ -1,11 +1,11 @@ | ||||||
| @font-face { | @font-face { | ||||||
|   font-family: 'fontello'; |   font-family: 'fontello'; | ||||||
|   src: url('../font/fontello.eot?94672585'); |   src: url('../font/fontello.eot?40679575'); | ||||||
|   src: url('../font/fontello.eot?94672585#iefix') format('embedded-opentype'), |   src: url('../font/fontello.eot?40679575#iefix') format('embedded-opentype'), | ||||||
|        url('../font/fontello.woff2?94672585') format('woff2'), |        url('../font/fontello.woff2?40679575') format('woff2'), | ||||||
|        url('../font/fontello.woff?94672585') format('woff'), |        url('../font/fontello.woff?40679575') format('woff'), | ||||||
|        url('../font/fontello.ttf?94672585') format('truetype'), |        url('../font/fontello.ttf?40679575') format('truetype'), | ||||||
|        url('../font/fontello.svg?94672585#fontello') format('svg'); |        url('../font/fontello.svg?40679575#fontello') format('svg'); | ||||||
|   font-weight: normal; |   font-weight: normal; | ||||||
|   font-style: normal; |   font-style: normal; | ||||||
| } | } | ||||||
|  | @ -15,7 +15,7 @@ | ||||||
| @media screen and (-webkit-min-device-pixel-ratio:0) { | @media screen and (-webkit-min-device-pixel-ratio:0) { | ||||||
|   @font-face { |   @font-face { | ||||||
|     font-family: 'fontello'; |     font-family: 'fontello'; | ||||||
|     src: url('../font/fontello.svg?94672585#fontello') format('svg'); |     src: url('../font/fontello.svg?40679575#fontello') format('svg'); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| */ | */ | ||||||
|  | @ -79,6 +79,7 @@ | ||||||
| .icon-plus:before { content: '\e815'; } /* '' */ | .icon-plus:before { content: '\e815'; } /* '' */ | ||||||
| .icon-adjust:before { content: '\e816'; } /* '' */ | .icon-adjust:before { content: '\e816'; } /* '' */ | ||||||
| .icon-edit:before { content: '\e817'; } /* '' */ | .icon-edit:before { content: '\e817'; } /* '' */ | ||||||
|  | .icon-pencil:before { content: '\e818'; } /* '' */ | ||||||
| .icon-spin3:before { content: '\e832'; } /* '' */ | .icon-spin3:before { content: '\e832'; } /* '' */ | ||||||
| .icon-spin4:before { content: '\e834'; } /* '' */ | .icon-spin4:before { content: '\e834'; } /* '' */ | ||||||
| .icon-link-ext:before { content: '\f08e'; } /* '' */ | .icon-link-ext:before { content: '\f08e'; } /* '' */ | ||||||
|  |  | ||||||
							
								
								
									
										17
									
								
								static/font/demo.html
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										17
									
								
								static/font/demo.html
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							|  | @ -229,11 +229,11 @@ body { | ||||||
| } | } | ||||||
| @font-face { | @font-face { | ||||||
|       font-family: 'fontello'; |       font-family: 'fontello'; | ||||||
|       src: url('./font/fontello.eot?28736547'); |       src: url('./font/fontello.eot?50378338'); | ||||||
|       src: url('./font/fontello.eot?28736547#iefix') format('embedded-opentype'), |       src: url('./font/fontello.eot?50378338#iefix') format('embedded-opentype'), | ||||||
|            url('./font/fontello.woff?28736547') format('woff'), |            url('./font/fontello.woff?50378338') format('woff'), | ||||||
|            url('./font/fontello.ttf?28736547') format('truetype'), |            url('./font/fontello.ttf?50378338') format('truetype'), | ||||||
|            url('./font/fontello.svg?28736547#fontello') format('svg'); |            url('./font/fontello.svg?50378338#fontello') format('svg'); | ||||||
|       font-weight: normal; |       font-weight: normal; | ||||||
|       font-style: normal; |       font-style: normal; | ||||||
|     } |     } | ||||||
|  | @ -334,24 +334,25 @@ body { | ||||||
|         <div class="the-icons span3" title="Code: 0xe817"><i class="demo-icon icon-edit"></i> <span class="i-name">icon-edit</span><span class="i-code">0xe817</span></div> |         <div class="the-icons span3" title="Code: 0xe817"><i class="demo-icon icon-edit"></i> <span class="i-name">icon-edit</span><span class="i-code">0xe817</span></div> | ||||||
|       </div> |       </div> | ||||||
|       <div class="row"> |       <div class="row"> | ||||||
|  |         <div class="the-icons span3" title="Code: 0xe818"><i class="demo-icon icon-pencil"></i> <span class="i-name">icon-pencil</span><span class="i-code">0xe818</span></div> | ||||||
|         <div class="the-icons span3" title="Code: 0xe832"><i class="demo-icon icon-spin3 animate-spin"></i> <span class="i-name">icon-spin3</span><span class="i-code">0xe832</span></div> |         <div class="the-icons span3" title="Code: 0xe832"><i class="demo-icon icon-spin3 animate-spin"></i> <span class="i-name">icon-spin3</span><span class="i-code">0xe832</span></div> | ||||||
|         <div class="the-icons span3" title="Code: 0xe834"><i class="demo-icon icon-spin4 animate-spin"></i> <span class="i-name">icon-spin4</span><span class="i-code">0xe834</span></div> |         <div class="the-icons span3" title="Code: 0xe834"><i class="demo-icon icon-spin4 animate-spin"></i> <span class="i-name">icon-spin4</span><span class="i-code">0xe834</span></div> | ||||||
|         <div class="the-icons span3" title="Code: 0xf08e"><i class="demo-icon icon-link-ext"></i> <span class="i-name">icon-link-ext</span><span class="i-code">0xf08e</span></div> |         <div class="the-icons span3" title="Code: 0xf08e"><i class="demo-icon icon-link-ext"></i> <span class="i-name">icon-link-ext</span><span class="i-code">0xf08e</span></div> | ||||||
|         <div class="the-icons span3" title="Code: 0xf08f"><i class="demo-icon icon-link-ext-alt"></i> <span class="i-name">icon-link-ext-alt</span><span class="i-code">0xf08f</span></div> |  | ||||||
|       </div> |       </div> | ||||||
|       <div class="row"> |       <div class="row"> | ||||||
|  |         <div class="the-icons span3" title="Code: 0xf08f"><i class="demo-icon icon-link-ext-alt"></i> <span class="i-name">icon-link-ext-alt</span><span class="i-code">0xf08f</span></div> | ||||||
|         <div class="the-icons span3" title="Code: 0xf0c9"><i class="demo-icon icon-menu"></i> <span class="i-name">icon-menu</span><span class="i-code">0xf0c9</span></div> |         <div class="the-icons span3" title="Code: 0xf0c9"><i class="demo-icon icon-menu"></i> <span class="i-name">icon-menu</span><span class="i-code">0xf0c9</span></div> | ||||||
|         <div class="the-icons span3" title="Code: 0xf0e0"><i class="demo-icon icon-mail-alt"></i> <span class="i-name">icon-mail-alt</span><span class="i-code">0xf0e0</span></div> |         <div class="the-icons span3" title="Code: 0xf0e0"><i class="demo-icon icon-mail-alt"></i> <span class="i-name">icon-mail-alt</span><span class="i-code">0xf0e0</span></div> | ||||||
|         <div class="the-icons span3" title="Code: 0xf0e5"><i class="demo-icon icon-comment-empty"></i> <span class="i-name">icon-comment-empty</span><span class="i-code">0xf0e5</span></div> |         <div class="the-icons span3" title="Code: 0xf0e5"><i class="demo-icon icon-comment-empty"></i> <span class="i-name">icon-comment-empty</span><span class="i-code">0xf0e5</span></div> | ||||||
|         <div class="the-icons span3" title="Code: 0xf0fe"><i class="demo-icon icon-plus-squared"></i> <span class="i-name">icon-plus-squared</span><span class="i-code">0xf0fe</span></div> |  | ||||||
|       </div> |       </div> | ||||||
|       <div class="row"> |       <div class="row"> | ||||||
|  |         <div class="the-icons span3" title="Code: 0xf0fe"><i class="demo-icon icon-plus-squared"></i> <span class="i-name">icon-plus-squared</span><span class="i-code">0xf0fe</span></div> | ||||||
|         <div class="the-icons span3" title="Code: 0xf112"><i class="demo-icon icon-reply"></i> <span class="i-name">icon-reply</span><span class="i-code">0xf112</span></div> |         <div class="the-icons span3" title="Code: 0xf112"><i class="demo-icon icon-reply"></i> <span class="i-name">icon-reply</span><span class="i-code">0xf112</span></div> | ||||||
|         <div class="the-icons span3" title="Code: 0xf13e"><i class="demo-icon icon-lock-open-alt"></i> <span class="i-name">icon-lock-open-alt</span><span class="i-code">0xf13e</span></div> |         <div class="the-icons span3" title="Code: 0xf13e"><i class="demo-icon icon-lock-open-alt"></i> <span class="i-name">icon-lock-open-alt</span><span class="i-code">0xf13e</span></div> | ||||||
|         <div class="the-icons span3" title="Code: 0xf144"><i class="demo-icon icon-play-circled"></i> <span class="i-name">icon-play-circled</span><span class="i-code">0xf144</span></div> |         <div class="the-icons span3" title="Code: 0xf144"><i class="demo-icon icon-play-circled"></i> <span class="i-name">icon-play-circled</span><span class="i-code">0xf144</span></div> | ||||||
|         <div class="the-icons span3" title="Code: 0xf164"><i class="demo-icon icon-thumbs-up-alt"></i> <span class="i-name">icon-thumbs-up-alt</span><span class="i-code">0xf164</span></div> |  | ||||||
|       </div> |       </div> | ||||||
|       <div class="row"> |       <div class="row"> | ||||||
|  |         <div class="the-icons span3" title="Code: 0xf164"><i class="demo-icon icon-thumbs-up-alt"></i> <span class="i-name">icon-thumbs-up-alt</span><span class="i-code">0xf164</span></div> | ||||||
|         <div class="the-icons span3" title="Code: 0xf1e5"><i class="demo-icon icon-binoculars"></i> <span class="i-name">icon-binoculars</span><span class="i-code">0xf1e5</span></div> |         <div class="the-icons span3" title="Code: 0xf1e5"><i class="demo-icon icon-binoculars"></i> <span class="i-name">icon-binoculars</span><span class="i-code">0xf1e5</span></div> | ||||||
|         <div class="the-icons span3" title="Code: 0xf234"><i class="demo-icon icon-user-plus"></i> <span class="i-name">icon-user-plus</span><span class="i-code">0xf234</span></div> |         <div class="the-icons span3" title="Code: 0xf234"><i class="demo-icon icon-user-plus"></i> <span class="i-name">icon-user-plus</span><span class="i-code">0xf234</span></div> | ||||||
|       </div> |       </div> | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								static/font/font/fontello.eot
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/font/font/fontello.eot
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										2
									
								
								static/font/font/fontello.svg
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										2
									
								
								static/font/font/fontello.svg
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							|  | @ -54,6 +54,8 @@ | ||||||
| 
 | 
 | ||||||
| <glyph glyph-name="edit" unicode="" d="M496 196l64 65-85 85-64-65v-31h53v-54h32z m245 402q-9 9-18 0l-196-196q-9-9 0-18t18 0l196 196q9 9 0 18z m45-331v-106q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q35 0 65-14 9-4 10-13 2-10-5-16l-27-28q-8-8-18-4-13 3-25 3h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v70q0 7 5 12l36 36q8 8 20 4t11-16z m-54 411l161-160-375-375h-161v160z m248-73l-51-52-161 161 51 52q16 15 38 15t38-15l85-85q16-16 16-38t-16-38z" horiz-adv-x="1000" /> | <glyph glyph-name="edit" unicode="" d="M496 196l64 65-85 85-64-65v-31h53v-54h32z m245 402q-9 9-18 0l-196-196q-9-9 0-18t18 0l196 196q9 9 0 18z m45-331v-106q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h464q35 0 65-14 9-4 10-13 2-10-5-16l-27-28q-8-8-18-4-13 3-25 3h-464q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v70q0 7 5 12l36 36q8 8 20 4t11-16z m-54 411l161-160-375-375h-161v160z m248-73l-51-52-161 161 51 52q16 15 38 15t38-15l85-85q16-16 16-38t-16-38z" horiz-adv-x="1000" /> | ||||||
| 
 | 
 | ||||||
|  | <glyph glyph-name="pencil" unicode="" d="M203 0l50 51-131 131-51-51v-60h72v-71h60z m291 518q0 12-12 12-5 0-9-4l-303-302q-4-4-4-10 0-12 13-12 5 0 9 4l303 302q3 4 3 10z m-30 107l232-232-464-465h-232v233z m381-54q0-29-20-50l-93-93-232 233 93 92q20 21 50 21 29 0 51-21l131-131q20-22 20-51z" horiz-adv-x="857.1" /> | ||||||
|  | 
 | ||||||
| <glyph glyph-name="spin3" unicode="" d="M494 857c-266 0-483-210-494-472-1-19 13-20 13-20l84 0c16 0 19 10 19 18 10 199 176 358 378 358 107 0 205-45 273-118l-58-57c-11-12-11-27 5-31l247-50c21-5 46 11 37 44l-58 227c-2 9-16 22-29 13l-65-60c-89 91-214 148-352 148z m409-508c-16 0-19-10-19-18-10-199-176-358-377-358-108 0-205 45-274 118l59 57c10 12 10 27-5 31l-248 50c-21 5-46-11-37-44l58-227c2-9 16-22 30-13l64 60c89-91 214-148 353-148 265 0 482 210 493 473 1 18-13 19-13 19l-84 0z" horiz-adv-x="1000" /> | <glyph glyph-name="spin3" unicode="" d="M494 857c-266 0-483-210-494-472-1-19 13-20 13-20l84 0c16 0 19 10 19 18 10 199 176 358 378 358 107 0 205-45 273-118l-58-57c-11-12-11-27 5-31l247-50c21-5 46 11 37 44l-58 227c-2 9-16 22-29 13l-65-60c-89 91-214 148-352 148z m409-508c-16 0-19-10-19-18-10-199-176-358-377-358-108 0-205 45-274 118l59 57c10 12 10 27-5 31l-248 50c-21 5-46-11-37-44l58-227c2-9 16-22 30-13l64 60c89-91 214-148 353-148 265 0 482 210 493 473 1 18-13 19-13 19l-84 0z" horiz-adv-x="1000" /> | ||||||
| 
 | 
 | ||||||
| <glyph glyph-name="spin4" unicode="" d="M498 857c-114 0-228-39-320-116l0 0c173 140 428 130 588-31 134-134 164-332 89-495-10-29-5-50 12-68 21-20 61-23 84 0 3 3 12 15 15 24 71 180 33 393-112 539-99 98-228 147-356 147z m-409-274c-14 0-29-5-39-16-3-3-13-15-15-24-71-180-34-393 112-539 185-185 479-195 676-31l0 0c-173-140-428-130-589 31-134 134-163 333-89 495 11 29 6 50-12 68-11 11-27 17-44 16z" horiz-adv-x="1001" /> | <glyph glyph-name="spin4" unicode="" d="M498 857c-114 0-228-39-320-116l0 0c173 140 428 130 588-31 134-134 164-332 89-495-10-29-5-50 12-68 21-20 61-23 84 0 3 3 12 15 15 24 71 180 33 393-112 539-99 98-228 147-356 147z m-409-274c-14 0-29-5-39-16-3-3-13-15-15-24-71-180-34-393 112-539 185-185 479-195 676-31l0 0c-173-140-428-130-589 31-134 134-163 333-89 495 11 29 6 50-12 68-11 11-27 17-44 16z" horiz-adv-x="1001" /> | ||||||
|  |  | ||||||
| Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/font/font/fontello.ttf
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/font/font/fontello.ttf
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								static/font/font/fontello.woff
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/font/font/fontello.woff
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								static/font/font/fontello.woff2
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/font/font/fontello.woff2
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							|  | @ -14,14 +14,15 @@ const makeMockStatus = ({id, text, type = 'status'}) => { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| describe('Statuses.prepareStatus', () => { | describe('Statuses module', () => { | ||||||
|  |   describe('prepareStatus', () => { | ||||||
|     it('sets deleted flag to false', () => { |     it('sets deleted flag to false', () => { | ||||||
|       const aStatus = makeMockStatus({id: '1', text: 'Hello oniichan'}) |       const aStatus = makeMockStatus({id: '1', text: 'Hello oniichan'}) | ||||||
|       expect(prepareStatus(aStatus).deleted).to.eq(false) |       expect(prepareStatus(aStatus).deleted).to.eq(false) | ||||||
|     }) |     }) | ||||||
| }) |   }) | ||||||
| 
 | 
 | ||||||
| describe('The Statuses module', () => { |   describe('addNewStatuses', () => { | ||||||
|     it('adds the status to allStatuses and to the given timeline', () => { |     it('adds the status to allStatuses and to the given timeline', () => { | ||||||
|       const state = defaultState() |       const state = defaultState() | ||||||
|       const status = makeMockStatus({id: '1'}) |       const status = makeMockStatus({id: '1'}) | ||||||
|  | @ -238,7 +239,25 @@ describe('The Statuses module', () => { | ||||||
|       expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1) |       expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1) | ||||||
|       expect(state.timelines.public.visibleStatuses[0].favorited).to.eql(true) |       expect(state.timelines.public.visibleStatuses[0].favorited).to.eql(true) | ||||||
|     }) |     }) | ||||||
|  |   }) | ||||||
| 
 | 
 | ||||||
|  |   describe('showNewStatuses', () => { | ||||||
|  |     it('resets the minId to the min of the visible statuses when adding new to visible statuses', () => { | ||||||
|  |       const state = defaultState() | ||||||
|  |       const status = makeMockStatus({ id: '10' }) | ||||||
|  |       mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) | ||||||
|  |       const newStatus = makeMockStatus({ id: '20' }) | ||||||
|  |       mutations.addNewStatuses(state, { statuses: [newStatus], showImmediately: false, timeline: 'public' }) | ||||||
|  |       state.timelines.public.minId = '5' | ||||||
|  |       mutations.showNewStatuses(state, { timeline: 'public' }) | ||||||
|  | 
 | ||||||
|  |       expect(state.timelines.public.visibleStatuses.length).to.eql(2) | ||||||
|  |       expect(state.timelines.public.minVisibleId).to.eql('10') | ||||||
|  |       expect(state.timelines.public.minId).to.eql('10') | ||||||
|  |     }) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   describe('clearTimeline', () => { | ||||||
|     it('keeps userId when clearing user timeline', () => { |     it('keeps userId when clearing user timeline', () => { | ||||||
|       const state = defaultState() |       const state = defaultState() | ||||||
|       state.timelines.user.userId = 123 |       state.timelines.user.userId = 123 | ||||||
|  | @ -247,6 +266,7 @@ describe('The Statuses module', () => { | ||||||
| 
 | 
 | ||||||
|       expect(state.timelines.user.userId).to.eql(123) |       expect(state.timelines.user.userId).to.eql(123) | ||||||
|     }) |     }) | ||||||
|  |   }) | ||||||
| 
 | 
 | ||||||
|   describe('notifications', () => { |   describe('notifications', () => { | ||||||
|     it('removes a notification when the notice gets removed', () => { |     it('removes a notification when the notice gets removed', () => { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Edijs
						Edijs