about summary refs log tree commit diff
path: root/app/javascript
diff options
context:
space:
mode:
Diffstat (limited to 'app/javascript')
-rw-r--r--app/javascript/flavours/glitch/features/getting_started/index.js3
-rw-r--r--app/javascript/flavours/glitch/features/ui/components/modal_root.js2
-rw-r--r--app/javascript/flavours/glitch/features/ui/index.js2
-rw-r--r--app/javascript/flavours/glitch/reducers/accounts.js6
-rw-r--r--app/javascript/flavours/glitch/reducers/accounts_counters.js6
-rw-r--r--app/javascript/flavours/glitch/reducers/index.js2
-rw-r--r--app/javascript/flavours/glitch/reducers/settings.js7
-rw-r--r--app/javascript/flavours/glitch/styles/components/index.scss84
-rw-r--r--app/javascript/flavours/glitch/util/async-components.js8
9 files changed, 120 insertions, 0 deletions
diff --git a/app/javascript/flavours/glitch/features/getting_started/index.js b/app/javascript/flavours/glitch/features/getting_started/index.js
index 2af0fcf48..469fc2aa7 100644
--- a/app/javascript/flavours/glitch/features/getting_started/index.js
+++ b/app/javascript/flavours/glitch/features/getting_started/index.js
@@ -29,6 +29,7 @@ const messages = defineMessages({
   info: { id: 'navigation_bar.info', defaultMessage: 'Extended information' },
   show_me_around: { id: 'getting_started.onboarding', defaultMessage: 'Show me around' },
   pins: { id: 'navigation_bar.pins', defaultMessage: 'Pinned toots' },
+  lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' },
 });
 
 const mapStateToProps = state => ({
@@ -87,6 +88,7 @@ export default class GettingStarted extends ImmutablePureComponent {
     navItems = navItems.concat([
       <ColumnLink key='5' icon='star' text={intl.formatMessage(messages.favourites)} to='/favourites' />,
       <ColumnLink key='6' icon='thumb-tack' text={intl.formatMessage(messages.pins)} to='/pinned' />,
+      <ColumnLink key='9' icon='bars' text={intl.formatMessage(messages.lists)} to='/lists' />,
     ]);
 
     if (myAccount.get('locked')) {
@@ -96,6 +98,7 @@ export default class GettingStarted extends ImmutablePureComponent {
     navItems = navItems.concat([
       <ColumnLink key='8' icon='volume-off' text={intl.formatMessage(messages.mutes)} to='/mutes' />,
       <ColumnLink key='9' icon='ban' text={intl.formatMessage(messages.blocks)} to='/blocks' />,
+      <ColumnLink key='10' icon='question' text={intl.formatMessage(messages.keyboard_shortcuts)} to='/keyboard-shortcuts' hideOnMobile />,
     ]);
 
     return (
diff --git a/app/javascript/flavours/glitch/features/ui/components/modal_root.js b/app/javascript/flavours/glitch/features/ui/components/modal_root.js
index 61b239283..679578b75 100644
--- a/app/javascript/flavours/glitch/features/ui/components/modal_root.js
+++ b/app/javascript/flavours/glitch/features/ui/components/modal_root.js
@@ -15,6 +15,7 @@ import {
   ReportModal,
   SettingsModal,
   EmbedModal,
+  ListEditor,
 } from 'flavours/glitch/util/async-components';
 
 const MODAL_COMPONENTS = {
@@ -29,6 +30,7 @@ const MODAL_COMPONENTS = {
   'SETTINGS': SettingsModal,
   'ACTIONS': () => Promise.resolve({ default: ActionsModal }),
   'EMBED': EmbedModal,
+  'LIST_EDITOR': ListEditor,
 };
 
 export default class ModalRoot extends React.PureComponent {
diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js
index 3dee7ca19..698ae996c 100644
--- a/app/javascript/flavours/glitch/features/ui/index.js
+++ b/app/javascript/flavours/glitch/features/ui/index.js
@@ -39,6 +39,7 @@ import {
   Blocks,
   Mutes,
   PinnedStatuses,
+  Lists,
 } from 'flavours/glitch/util/async-components';
 import { HotKeys } from 'react-hotkeys';
 import { me } from 'flavours/glitch/util/initial_state';
@@ -426,6 +427,7 @@ export default class UI extends React.Component {
               <WrappedRoute path='/follow_requests' component={FollowRequests} content={children} />
               <WrappedRoute path='/blocks' component={Blocks} content={children} />
               <WrappedRoute path='/mutes' component={Mutes} content={children} />
+              <WrappedRoute path='/lists' component={Lists} content={children} />
 
               <WrappedRoute component={GenericNotFound} content={children} />
             </WrappedSwitch>
diff --git a/app/javascript/flavours/glitch/reducers/accounts.js b/app/javascript/flavours/glitch/reducers/accounts.js
index 5113a281a..9ca05881a 100644
--- a/app/javascript/flavours/glitch/reducers/accounts.js
+++ b/app/javascript/flavours/glitch/reducers/accounts.js
@@ -43,6 +43,10 @@ import {
   FAVOURITED_STATUSES_FETCH_SUCCESS,
   FAVOURITED_STATUSES_EXPAND_SUCCESS,
 } from 'flavours/glitch/actions/favourites';
+import {
+  LIST_ACCOUNTS_FETCH_SUCCESS,
+  LIST_EDITOR_SUGGESTIONS_READY,
+} from 'flavours/glitch/actions/lists';
 import { STORE_HYDRATE } from 'flavours/glitch/actions/store';
 import emojify from 'flavours/glitch/util/emoji';
 import { Map as ImmutableMap, fromJS } from 'immutable';
@@ -110,6 +114,8 @@ export default function accounts(state = initialState, action) {
   case BLOCKS_EXPAND_SUCCESS:
   case MUTES_FETCH_SUCCESS:
   case MUTES_EXPAND_SUCCESS:
+  case LIST_ACCOUNTS_FETCH_SUCCESS:
+  case LIST_EDITOR_SUGGESTIONS_READY:
     return action.accounts ? normalizeAccounts(state, action.accounts) : state;
   case NOTIFICATIONS_REFRESH_SUCCESS:
   case NOTIFICATIONS_EXPAND_SUCCESS:
diff --git a/app/javascript/flavours/glitch/reducers/accounts_counters.js b/app/javascript/flavours/glitch/reducers/accounts_counters.js
index a9aebd26f..0fd985a08 100644
--- a/app/javascript/flavours/glitch/reducers/accounts_counters.js
+++ b/app/javascript/flavours/glitch/reducers/accounts_counters.js
@@ -45,6 +45,10 @@ import {
   FAVOURITED_STATUSES_FETCH_SUCCESS,
   FAVOURITED_STATUSES_EXPAND_SUCCESS,
 } from 'flavours/glitch/actions/favourites';
+import {
+  LIST_ACCOUNTS_FETCH_SUCCESS,
+  LIST_EDITOR_SUGGESTIONS_READY,
+} from 'flavours/glitch/actions/lists';
 import { STORE_HYDRATE } from 'flavours/glitch/actions/store';
 import { Map as ImmutableMap, fromJS } from 'immutable';
 
@@ -106,6 +110,8 @@ export default function accountsCounters(state = initialState, action) {
   case BLOCKS_EXPAND_SUCCESS:
   case MUTES_FETCH_SUCCESS:
   case MUTES_EXPAND_SUCCESS:
+  case LIST_ACCOUNTS_FETCH_SUCCESS:
+  case LIST_EDITOR_SUGGESTIONS_READY:
     return action.accounts ? normalizeAccounts(state, action.accounts) : state;
   case NOTIFICATIONS_REFRESH_SUCCESS:
   case NOTIFICATIONS_EXPAND_SUCCESS:
diff --git a/app/javascript/flavours/glitch/reducers/index.js b/app/javascript/flavours/glitch/reducers/index.js
index 25baaef71..e9c8d7c1d 100644
--- a/app/javascript/flavours/glitch/reducers/index.js
+++ b/app/javascript/flavours/glitch/reducers/index.js
@@ -24,6 +24,7 @@ import notifications from './notifications';
 import height_cache from './height_cache';
 import custom_emojis from './custom_emojis';
 import lists from './lists';
+import listEditor from './list_editor';
 
 const reducers = {
   timelines,
@@ -51,6 +52,7 @@ const reducers = {
   height_cache,
   custom_emojis,
   lists,
+  listEditor,
 };
 
 export default combineReducers(reducers);
diff --git a/app/javascript/flavours/glitch/reducers/settings.js b/app/javascript/flavours/glitch/reducers/settings.js
index 6d5d71217..aaf7938df 100644
--- a/app/javascript/flavours/glitch/reducers/settings.js
+++ b/app/javascript/flavours/glitch/reducers/settings.js
@@ -2,6 +2,7 @@ import { SETTING_CHANGE, SETTING_SAVE } from 'flavours/glitch/actions/settings';
 import { COLUMN_ADD, COLUMN_REMOVE, COLUMN_MOVE } from 'flavours/glitch/actions/columns';
 import { STORE_HYDRATE } from 'flavours/glitch/actions/store';
 import { EMOJI_USE } from 'flavours/glitch/actions/emojis';
+import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from '../actions/lists';
 import { Map as ImmutableMap, fromJS } from 'immutable';
 import uuid from 'flavours/glitch/util/uuid';
 
@@ -92,6 +93,8 @@ const moveColumn = (state, uuid, direction) => {
 
 const updateFrequentEmojis = (state, emoji) => state.update('frequentlyUsedEmojis', ImmutableMap(), map => map.update(emoji.id, 0, count => count + 1)).set('saved', false);
 
+const filterDeadListColumns = (state, listId) => state.update('columns', columns => columns.filterNot(column => column.get('id') === 'LIST' && column.get('params').get('id') === listId));
+
 export default function settings(state = initialState, action) {
   switch(action.type) {
   case STORE_HYDRATE:
@@ -114,6 +117,10 @@ export default function settings(state = initialState, action) {
     return updateFrequentEmojis(state, action.emoji);
   case SETTING_SAVE:
     return state.set('saved', true);
+  case LIST_FETCH_FAIL:
+    return action.error.response.status === 404 ? filterDeadListColumns(state, action.id) : state;
+  case LIST_DELETE_SUCCESS:
+    return filterDeadListColumns(state, action.id);
   default:
     return state;
   }
diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss
index 7aeab0a6a..147690562 100644
--- a/app/javascript/flavours/glitch/styles/components/index.scss
+++ b/app/javascript/flavours/glitch/styles/components/index.scss
@@ -4827,6 +4827,90 @@ noscript {
   }
 }
 
+
+.column-inline-form {
+  padding: 7px 15px;
+  padding-right: 5px;
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  background: lighten($ui-base-color, 4%);
+
+  label {
+    flex: 1 1 auto;
+
+    input {
+      width: 100%;
+      margin-bottom: 6px;
+    }
+  }
+
+  .icon-button {
+    flex: 0 0 auto;
+    margin-left: 5px;
+  }
+}
+
+.drawer__backdrop {
+  cursor: pointer;
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba($base-overlay-background, 0.5);
+}
+
+.list-editor {
+  background: $ui-base-color;
+  flex-direction: column;
+  border-radius: 8px;
+  box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4);
+  width: 40vh;
+  overflow: hidden;
+
+  h4 {
+    padding: 15px 0;
+    background: lighten($ui-base-color, 13%);
+    font-weight: 500;
+    font-size: 16px;
+    text-align: center;
+    border-radius: 8px 8px 0 0;
+  }
+
+  .drawer__pager {
+    height: 50vh;
+  }
+
+  .drawer__inner {
+    border-radius: 0 0 8px 8px;
+
+    &.backdrop {
+      width: calc(100% - 60px);
+      box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4);
+      border-radius: 0 0 0 8px;
+    }
+  }
+
+  &__accounts {
+    overflow-y: auto;
+  }
+
+  .account__display-name {
+    &:hover strong {
+      text-decoration: none;
+    }
+  }
+
+  .account__avatar {
+    cursor: default;
+  }
+
+  .search {
+    margin-bottom: 0;
+  }
+}
+
 @import 'doodle';
 @import 'emoji_picker';
 @import 'local_settings';
diff --git a/app/javascript/flavours/glitch/util/async-components.js b/app/javascript/flavours/glitch/util/async-components.js
index 3056deab2..e4c991f01 100644
--- a/app/javascript/flavours/glitch/util/async-components.js
+++ b/app/javascript/flavours/glitch/util/async-components.js
@@ -30,6 +30,14 @@ export function ListTimeline () {
   return import(/* webpackChunkName: "features/list_timeline" */'flavours/glitch/features/list_timeline');
 }
 
+export function Lists () {
+  return import(/* webpackChunkName: "features/lists" */'flavours/glitch/features/lists');
+}
+
+export function ListEditor () {
+  return import(/* webpackChunkName: "features/list_editor" */'flavours/glitch/features/list_editor');
+}
+
 export function DirectTimeline() {
   return import(/* webpackChunkName: "flavours/glitch/async/direct_timeline" */'flavours/glitch/features/direct_timeline');
 }