From b48a3210a3056385484e60551dd601177839b6cd Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 28 Aug 2018 14:28:05 +0300
Subject: tabs for settings

---
 src/components/settings/settings.vue | 169 +++++++++++++++++++----------------
 1 file changed, 91 insertions(+), 78 deletions(-)

(limited to 'src/components/settings/settings.vue')

diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index f500a1b0..923c6970 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -4,90 +4,99 @@
     {{$t('settings.settings')}}
   </div>
   <div class="panel-body">
-    <div class="setting-item">
-      <h2>{{$t('settings.theme')}}</h2>
-      <style-switcher></style-switcher>
-    </div>
-    <div class="setting-item">
-      <h2>{{$t('settings.filtering')}}</h2>
-      <p>{{$t('settings.filtering_explanation')}}</p>
-      <textarea id="muteWords" v-model="muteWordsString"></textarea>
-    </div>
-    <div class="setting-item">
-      <h2>{{$t('nav.timeline')}}</h2>
-      <ul class="setting-list">
-        <li>
-          <input type="checkbox" id="collapseMessageWithSubject" v-model="collapseMessageWithSubjectLocal">
-          <label for="collapseMessageWithSubject">{{$t('settings.collapse_subject')}}</label>
-        </li>
-        <li>
-          <input type="checkbox" id="streaming" v-model="streamingLocal">
-          <label for="streaming">{{$t('settings.streaming')}}</label>
-          <ul class="setting-list suboptions" :class="[{disabled: !streamingLocal}]">
+    <tab-switcher>
+      <div :title="$t('settings.general')" >
+        <div class="setting-item">
+          <h2>{{ $t('settings.interfaceLanguage') }}</h2>
+          <interface-language-switcher />
+        </div>
+        <div class="setting-item">
+          <h2>{{$t('nav.timeline')}}</h2>
+          <ul class="setting-list">
             <li>
-              <input :disabled="!streamingLocal" type="checkbox" id="pauseOnUnfocused" v-model="pauseOnUnfocusedLocal">
-              <label for="pauseOnUnfocused">{{$t('settings.pause_on_unfocused')}}</label>
+              <input type="checkbox" id="collapseMessageWithSubject" v-model="collapseMessageWithSubjectLocal">
+              <label for="collapseMessageWithSubject">{{$t('settings.collapse_subject')}}</label>
+            </li>
+            <li>
+              <input type="checkbox" id="streaming" v-model="streamingLocal">
+              <label for="streaming">{{$t('settings.streaming')}}</label>
+              <ul class="setting-list suboptions" :class="[{disabled: !streamingLocal}]">
+                <li>
+                  <input :disabled="!streamingLocal" type="checkbox" id="pauseOnUnfocused" v-model="pauseOnUnfocusedLocal">
+                  <label for="pauseOnUnfocused">{{$t('settings.pause_on_unfocused')}}</label>
+                </li>
+              </ul>
+            </li>
+            <li>
+              <input type="checkbox" id="autoload" v-model="autoLoadLocal">
+              <label for="autoload">{{$t('settings.autoload')}}</label>
+            </li>
+            <li>
+              <input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal">
+              <label for="hoverPreview">{{$t('settings.reply_link_preview')}}</label>
+            </li>
+            <li>
+              <label for="replyVisibility" class="select">
+                <select id="replyVisibility" v-model="replyVisibilityLocal">
+                  <option value="all" selected>{{$t('settings.reply_visibility_all')}}</option>
+                  <option value="following">{{$t('settings.reply_visibility_following')}}</option>
+                  <option value="self">{{$t('settings.reply_visibility_self')}}</option>
+                </select>
+                <i class="icon-down-open"/>
+              </label>
             </li>
           </ul>
-        </li>
-        <li>
-          <input type="checkbox" id="autoload" v-model="autoLoadLocal">
-          <label for="autoload">{{$t('settings.autoload')}}</label>
-        </li>
-        <li>
-          <input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal">
-          <label for="hoverPreview">{{$t('settings.reply_link_preview')}}</label>
-        </li>
-        <li>
-          <label for="replyVisibility" class="select">
-            <select id="replyVisibility" v-model="replyVisibilityLocal">
-              <option value="all" selected>{{$t('settings.reply_visibility_all')}}</option>
-              <option value="following">{{$t('settings.reply_visibility_following')}}</option>
-              <option value="self">{{$t('settings.reply_visibility_self')}}</option>
-            </select>
-            <i class="icon-down-open"/>
-          </label>
-        </li>
-      </ul>
-    </div>
-    <div class="setting-item">
-      <h2>{{$t('settings.attachments')}}</h2>
-      <ul class="setting-list">
-        <li>
-          <input type="checkbox" id="hideAttachments" v-model="hideAttachmentsLocal">
-          <label for="hideAttachments">{{$t('settings.hide_attachments_in_tl')}}</label>
-        </li>
-        <li>
-          <input type="checkbox" id="hideAttachmentsInConv" v-model="hideAttachmentsInConvLocal">
-          <label for="hideAttachmentsInConv">{{$t('settings.hide_attachments_in_convo')}}</label>
-        </li>
-        <li>
-          <input type="checkbox" id="hideNsfw" v-model="hideNsfwLocal">
-          <label for="hideNsfw">{{$t('settings.nsfw_clickthrough')}}</label>
-        </li>
-        <li>
-          <input type="checkbox" id="stopGifs" v-model="stopGifs">
-          <label for="stopGifs">{{$t('settings.stop_gifs')}}</label>
-        </li>
-        <li>
-          <input type="checkbox" id="loopVideo" v-model="loopVideoLocal">
-          <label for="loopVideo">{{$t('settings.loop_video')}}</label>
-          <ul class="setting-list suboptions" :class="[{disabled: !streamingLocal}]">
+        </div>
+        <div class="setting-item">
+          <h2>{{$t('settings.attachments')}}</h2>
+          <ul class="setting-list">
             <li>
-              <input :disabled="!loopVideoLocal || !loopSilentAvailable" type="checkbox" id="loopVideoSilentOnly" v-model="loopVideoSilentOnlyLocal">
-              <label for="loopVideoSilentOnly">{{$t('settings.loop_video_silent_only')}}</label>
-              <div v-if="!loopSilentAvailable" class="unavailable">
-                <i class="icon-globe"/>! {{$t('settings.limited_availability')}}
-              </div>
+              <input type="checkbox" id="hideAttachments" v-model="hideAttachmentsLocal">
+              <label for="hideAttachments">{{$t('settings.hide_attachments_in_tl')}}</label>
+            </li>
+            <li>
+              <input type="checkbox" id="hideAttachmentsInConv" v-model="hideAttachmentsInConvLocal">
+              <label for="hideAttachmentsInConv">{{$t('settings.hide_attachments_in_convo')}}</label>
+            </li>
+            <li>
+              <input type="checkbox" id="hideNsfw" v-model="hideNsfwLocal">
+              <label for="hideNsfw">{{$t('settings.nsfw_clickthrough')}}</label>
+            </li>
+            <li>
+              <input type="checkbox" id="stopGifs" v-model="stopGifs">
+              <label for="stopGifs">{{$t('settings.stop_gifs')}}</label>
+            </li>
+            <li>
+              <input type="checkbox" id="loopVideo" v-model="loopVideoLocal">
+              <label for="loopVideo">{{$t('settings.loop_video')}}</label>
+              <ul class="setting-list suboptions" :class="[{disabled: !streamingLocal}]">
+                <li>
+                  <input :disabled="!loopVideoLocal || !loopSilentAvailable" type="checkbox" id="loopVideoSilentOnly" v-model="loopVideoSilentOnlyLocal">
+                  <label for="loopVideoSilentOnly">{{$t('settings.loop_video_silent_only')}}</label>
+                  <div v-if="!loopSilentAvailable" class="unavailable">
+                    <i class="icon-globe"/>! {{$t('settings.limited_availability')}}
+                  </div>
+                </li>
+              </ul>
             </li>
           </ul>
-        </li>
-      </ul>
-    </div>
-    <div class="setting-item">
-      <h2>{{ $t('settings.interfaceLanguage') }}</h2>
-      <interface-language-switcher />
-    </div>
+        </div>
+      </div>
+
+      <div :title="$t('settings.theme')" >
+        <div class="setting-item">
+          <style-switcher></style-switcher>
+        </div>
+      </div>
+
+      <div :title="$t('settings.filtering')" >
+        <div class="setting-item">
+          <p>{{$t('settings.filtering_explanation')}}</p>
+          <textarea id="muteWords" v-model="muteWordsString"></textarea>
+        </div>
+      </div>
+
+    </tab-switcher>
   </div>
 </div>
 </template>
@@ -103,6 +112,10 @@
   margin: 1em 1em 1.4em;
   padding-bottom: 1.4em;
 
+  &:last-child {
+    border-bottom: none;
+  }
+
 
   textarea {
     width: 100%;
-- 
cgit v1.2.3-70-g09d2


From cff4177bf3a7622fa41542c380c462a70359b258 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 28 Aug 2018 15:38:07 +0300
Subject: settings page update

---
 src/components/settings/settings.vue             |  12 +-
 src/components/style_switcher/style_switcher.vue | 230 ++++++++++++++---------
 src/i18n/messages.js                             |  12 +-
 3 files changed, 157 insertions(+), 97 deletions(-)

(limited to 'src/components/settings/settings.vue')

diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index 923c6970..240cd70a 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -114,6 +114,12 @@
 
   &:last-child {
     border-bottom: none;
+    padding-bottom: 0;
+    margin-bottom: 1em;
+  }
+
+  select {
+    min-width: 10em;
   }
 
 
@@ -143,8 +149,12 @@
   }
 
   .btn {
-    margin-top: 1em;
     min-height: 28px;
+  }
+
+  .submit {
+    margin-top: 1em;
+    min-height: 30px;
     width: 10em;
   }
 }
diff --git a/src/components/style_switcher/style_switcher.vue b/src/components/style_switcher/style_switcher.vue
index 59bd2971..72a338bd 100644
--- a/src/components/style_switcher/style_switcher.vue
+++ b/src/components/style_switcher/style_switcher.vue
@@ -1,102 +1,30 @@
 <template>
-  <div>
-    <div>{{$t('settings.presets')}}
+<div>
+  <div class="presets-container">
+    <div>
+      {{$t('settings.presets')}}
       <label for="style-switcher" class='select'>
         <select id="style-switcher" v-model="selected" class="style-switcher">
-          <option v-for="style in availableStyles" :value="style" :style="{
-                  backgroundColor: style[1],
-                  color: style[3]
-                  }">{{style[0]}}</option>
+          <option v-for="style in availableStyles"
+                  :value="style"
+                  :style="{
+                          backgroundColor: style[1],
+                          color: style[3]
+                          }">
+            {{style[0]}}
+          </option>
         </select>
         <i class="icon-down-open"/>
       </label>
     </div>
-    <div>
+    <div class="import-export">
       <button class="btn" @click="exportCurrentTheme">{{ $t('settings.export_theme') }}</button>
       <button class="btn" @click="importTheme">{{ $t('settings.import_theme') }}</button>
       <p v-if="invalidThemeImported" class="import-warning">{{ $t('settings.invalid_theme_imported') }}</p>
     </div>
-    <div class="color-container">
-      <p>{{$t('settings.theme_help')}}</p>
-      <div class="color-item">
-        <label for="bgcolor" class="theme-color-lb">{{$t('settings.background')}}</label>
-        <input id="bgcolor" class="theme-color-cl" type="color" v-model="bgColorLocal">
-        <input id="bgcolor-t" class="theme-color-in" type="text" v-model="bgColorLocal">
-      </div>
-      <div class="color-item">
-        <label for="fgcolor" class="theme-color-lb">{{$t('settings.foreground')}}</label>
-        <input id="fgcolor" class="theme-color-cl" type="color" v-model="btnColorLocal">
-        <input id="fgcolor-t" class="theme-color-in" type="text" v-model="btnColorLocal">
-      </div>
-      <div class="color-item">
-        <label for="textcolor" class="theme-color-lb">{{$t('settings.text')}}</label>
-        <input id="textcolor" class="theme-color-cl" type="color" v-model="textColorLocal">
-        <input id="textcolor-t" class="theme-color-in" type="text" v-model="textColorLocal">
-      </div>
-      <div class="color-item">
-        <label for="linkcolor" class="theme-color-lb">{{$t('settings.links')}}</label>
-        <input id="linkcolor" class="theme-color-cl" type="color" v-model="linkColorLocal">
-        <input id="linkcolor-t" class="theme-color-in" type="text" v-model="linkColorLocal">
-      </div>
-      <div class="color-item">
-        <label for="redcolor" class="theme-color-lb">{{$t('settings.cRed')}}</label>
-        <input id="redcolor" class="theme-color-cl" type="color" v-model="redColorLocal">
-        <input id="redcolor-t" class="theme-color-in" type="text" v-model="redColorLocal">
-      </div>
-      <div class="color-item">
-        <label for="bluecolor" class="theme-color-lb">{{$t('settings.cBlue')}}</label>
-        <input id="bluecolor" class="theme-color-cl" type="color" v-model="blueColorLocal">
-        <input id="bluecolor-t" class="theme-color-in" type="text" v-model="blueColorLocal">
-      </div>
-      <div class="color-item">
-        <label for="greencolor" class="theme-color-lb">{{$t('settings.cGreen')}}</label>
-        <input id="greencolor" class="theme-color-cl" type="color" v-model="greenColorLocal">
-        <input id="greencolor-t" class="theme-color-in" type="green" v-model="greenColorLocal">
-      </div>
-      <div class="color-item">
-        <label for="orangecolor" class="theme-color-lb">{{$t('settings.cOrange')}}</label>
-        <input id="orangecolor" class="theme-color-cl" type="color" v-model="orangeColorLocal">
-        <input id="orangecolor-t" class="theme-color-in" type="text" v-model="orangeColorLocal">
-      </div>
-    </div>
-    <div class="radius-container">
-      <p>{{$t('settings.radii_help')}}</p>
-      <div class="radius-item">
-        <label for="btnradius" class="theme-radius-lb">{{$t('settings.btnRadius')}}</label>
-        <input id="btnradius" class="theme-radius-rn" type="range" v-model="btnRadiusLocal" max="16">
-        <input id="btnradius-t" class="theme-radius-in" type="text" v-model="btnRadiusLocal">
-      </div>
-      <div class="radius-item">
-        <label for="inputradius" class="theme-radius-lb">{{$t('settings.inputRadius')}}</label>
-        <input id="inputradius" class="theme-radius-rn" type="range" v-model="inputRadiusLocal" max="16">
-        <input id="inputradius-t" class="theme-radius-in" type="text" v-model="inputRadiusLocal">
-      </div>
-      <div class="radius-item">
-        <label for="panelradius" class="theme-radius-lb">{{$t('settings.panelRadius')}}</label>
-        <input id="panelradius" class="theme-radius-rn" type="range" v-model="panelRadiusLocal" max="50">
-        <input id="panelradius-t" class="theme-radius-in" type="text" v-model="panelRadiusLocal">
-      </div>
-      <div class="radius-item">
-        <label for="avatarradius" class="theme-radius-lb">{{$t('settings.avatarRadius')}}</label>
-        <input id="avatarradius" class="theme-radius-rn" type="range" v-model="avatarRadiusLocal" max="28">
-        <input id="avatarradius-t" class="theme-radius-in" type="green" v-model="avatarRadiusLocal">
-      </div>
-      <div class="radius-item">
-        <label for="avataraltradius" class="theme-radius-lb">{{$t('settings.avatarAltRadius')}}</label>
-        <input id="avataraltradius" class="theme-radius-rn" type="range" v-model="avatarAltRadiusLocal" max="28">
-        <input id="avataraltradius-t" class="theme-radius-in" type="text" v-model="avatarAltRadiusLocal">
-      </div>
-      <div class="radius-item">
-        <label for="attachmentradius" class="theme-radius-lb">{{$t('settings.attachmentRadius')}}</label>
-        <input id="attachmentrradius" class="theme-radius-rn" type="range" v-model="attachmentRadiusLocal" max="50">
-        <input id="attachmentradius-t" class="theme-radius-in" type="text" v-model="attachmentRadiusLocal">
-      </div>
-      <div class="radius-item">
-        <label for="tooltipradius" class="theme-radius-lb">{{$t('settings.tooltipRadius')}}</label>
-        <input id="tooltipradius" class="theme-radius-rn" type="range" v-model="tooltipRadiusLocal" max="20">
-        <input id="tooltipradius-t" class="theme-radius-in" type="text" v-model="tooltipRadiusLocal">
-      </div>
-    </div>
+  </div>
+
+  <div class="preview-container">
     <div :style="{
                  '--btnRadius': btnRadiusLocal + 'px',
                  '--inputRadius': inputRadiusLocal + 'px',
@@ -127,8 +55,95 @@
         </div>
       </div>
     </div>
-    <button class="btn" @click="setCustomTheme">{{$t('general.apply')}}</button>
   </div>
+
+  <div class="color-container">
+    <p>{{$t('settings.theme_help')}}</p>
+    <div class="color-item">
+      <label for="bgcolor" class="theme-color-lb">{{$t('settings.background')}}</label>
+      <input id="bgcolor" class="theme-color-cl" type="color" v-model="bgColorLocal">
+      <input id="bgcolor-t" class="theme-color-in" type="text" v-model="bgColorLocal">
+    </div>
+    <div class="color-item">
+      <label for="fgcolor" class="theme-color-lb">{{$t('settings.foreground')}}</label>
+      <input id="fgcolor" class="theme-color-cl" type="color" v-model="btnColorLocal">
+      <input id="fgcolor-t" class="theme-color-in" type="text" v-model="btnColorLocal">
+    </div>
+    <div class="color-item">
+      <label for="textcolor" class="theme-color-lb">{{$t('settings.text')}}</label>
+      <input id="textcolor" class="theme-color-cl" type="color" v-model="textColorLocal">
+      <input id="textcolor-t" class="theme-color-in" type="text" v-model="textColorLocal">
+    </div>
+    <div class="color-item">
+      <label for="linkcolor" class="theme-color-lb">{{$t('settings.links')}}</label>
+      <input id="linkcolor" class="theme-color-cl" type="color" v-model="linkColorLocal">
+      <input id="linkcolor-t" class="theme-color-in" type="text" v-model="linkColorLocal">
+    </div>
+    <div class="color-item">
+      <label for="redcolor" class="theme-color-lb">{{$t('settings.cRed')}}</label>
+      <input id="redcolor" class="theme-color-cl" type="color" v-model="redColorLocal">
+      <input id="redcolor-t" class="theme-color-in" type="text" v-model="redColorLocal">
+    </div>
+    <div class="color-item">
+      <label for="bluecolor" class="theme-color-lb">{{$t('settings.cBlue')}}</label>
+      <input id="bluecolor" class="theme-color-cl" type="color" v-model="blueColorLocal">
+      <input id="bluecolor-t" class="theme-color-in" type="text" v-model="blueColorLocal">
+    </div>
+    <div class="color-item">
+      <label for="greencolor" class="theme-color-lb">{{$t('settings.cGreen')}}</label>
+      <input id="greencolor" class="theme-color-cl" type="color" v-model="greenColorLocal">
+      <input id="greencolor-t" class="theme-color-in" type="green" v-model="greenColorLocal">
+    </div>
+    <div class="color-item">
+      <label for="orangecolor" class="theme-color-lb">{{$t('settings.cOrange')}}</label>
+      <input id="orangecolor" class="theme-color-cl" type="color" v-model="orangeColorLocal">
+      <input id="orangecolor-t" class="theme-color-in" type="text" v-model="orangeColorLocal">
+    </div>
+  </div>
+
+  <div class="radius-container">
+    <p>{{$t('settings.radii_help')}}</p>
+    <div class="radius-item">
+      <label for="btnradius" class="theme-radius-lb">{{$t('settings.btnRadius')}}</label>
+      <input id="btnradius" class="theme-radius-rn" type="range" v-model="btnRadiusLocal" max="16">
+      <input id="btnradius-t" class="theme-radius-in" type="text" v-model="btnRadiusLocal">
+    </div>
+    <div class="radius-item">
+      <label for="inputradius" class="theme-radius-lb">{{$t('settings.inputRadius')}}</label>
+      <input id="inputradius" class="theme-radius-rn" type="range" v-model="inputRadiusLocal" max="16">
+      <input id="inputradius-t" class="theme-radius-in" type="text" v-model="inputRadiusLocal">
+    </div>
+    <div class="radius-item">
+      <label for="panelradius" class="theme-radius-lb">{{$t('settings.panelRadius')}}</label>
+      <input id="panelradius" class="theme-radius-rn" type="range" v-model="panelRadiusLocal" max="50">
+      <input id="panelradius-t" class="theme-radius-in" type="text" v-model="panelRadiusLocal">
+    </div>
+    <div class="radius-item">
+      <label for="avatarradius" class="theme-radius-lb">{{$t('settings.avatarRadius')}}</label>
+      <input id="avatarradius" class="theme-radius-rn" type="range" v-model="avatarRadiusLocal" max="28">
+      <input id="avatarradius-t" class="theme-radius-in" type="green" v-model="avatarRadiusLocal">
+    </div>
+    <div class="radius-item">
+      <label for="avataraltradius" class="theme-radius-lb">{{$t('settings.avatarAltRadius')}}</label>
+      <input id="avataraltradius" class="theme-radius-rn" type="range" v-model="avatarAltRadiusLocal" max="28">
+      <input id="avataraltradius-t" class="theme-radius-in" type="text" v-model="avatarAltRadiusLocal">
+    </div>
+    <div class="radius-item">
+      <label for="attachmentradius" class="theme-radius-lb">{{$t('settings.attachmentRadius')}}</label>
+      <input id="attachmentrradius" class="theme-radius-rn" type="range" v-model="attachmentRadiusLocal" max="50">
+      <input id="attachmentradius-t" class="theme-radius-in" type="text" v-model="attachmentRadiusLocal">
+    </div>
+    <div class="radius-item">
+      <label for="tooltipradius" class="theme-radius-lb">{{$t('settings.tooltipRadius')}}</label>
+      <input id="tooltipradius" class="theme-radius-rn" type="range" v-model="tooltipRadiusLocal" max="20">
+      <input id="tooltipradius-t" class="theme-radius-in" type="text" v-model="tooltipRadiusLocal">
+    </div>
+  </div>
+
+  <div class="apply-container">
+    <button class="btn submit" @click="setCustomTheme">{{$t('general.apply')}}</button>
+  </div>
+</div>
 </template>
 
 <script src="./style_switcher.js"></script>
@@ -144,15 +159,19 @@
   color: var(--cRed, $fallback--cRed);
 }
 
+.apply-container,
 .radius-container,
-.color-container {
+.color-container,
+.presets-container {
   display: flex;
 
   p {
+    flex: 2 0 100%;
     margin-top: 2em;
     margin-bottom: .5em;
   }
 }
+
 .radius-container {
   flex-direction: column;
 }
@@ -162,6 +181,36 @@
   justify-content: space-between;
 }
 
+.presets-container {
+  justify-content: center;
+  .import-export {
+    display: flex;
+
+    .btn {
+      margin-left: .5em;
+    }
+  }
+}
+
+.preview-container {
+  border-top: 1px dashed;
+  border-bottom: 1px dashed;
+  border-color: $fallback--border;
+  border-color: var(--border, $fallback--border);
+  margin: 1em -1em 0;
+  padding: 1em;
+
+  .btn {
+    margin-top: 1em;
+    min-height: 30px;
+    width: 10em;
+  }
+}
+
+.apply-container {
+  justify-content: center;
+}
+
 .radius-item,
 .color-item {
   min-width: 20em;
@@ -229,6 +278,7 @@
   flex: 0;
   min-width: 2em;
   cursor: pointer;
+  max-height: 29px;
 }
 
 .theme-preview-content {
diff --git a/src/i18n/messages.js b/src/i18n/messages.js
index cd8fa512..cccf48cc 100644
--- a/src/i18n/messages.js
+++ b/src/i18n/messages.js
@@ -48,8 +48,8 @@ const de = {
     settings: 'Einstellungen',
     theme: 'Farbschema',
     presets: 'Voreinstellungen',
-    export_theme: 'Aktuelles Theme exportieren',
-    import_theme: 'Gespeichertes Theme laden',
+    export_theme: 'Farbschema speichern',
+    import_theme: 'Farbschema laden',
     invalid_theme_imported: 'Die ausgewählte Datei ist kein unterstütztes Pleroma-Theme. Keine Änderungen wurden vorgenommen.',
     theme_help: 'Benutze HTML Farbcodes (#rrggbb) um dein Farbschema anzupassen',
     radii_help: 'Kantenrundung (in Pixel) der Oberfläche anpassen',
@@ -293,8 +293,8 @@ const en = {
     settings: 'Settings',
     theme: 'Theme',
     presets: 'Presets',
-    export_theme: 'Export current theme',
-    import_theme: 'Load saved theme',
+    export_theme: 'Save preset',
+    import_theme: 'Load preset',
     theme_help: 'Use hex color codes (#rrggbb) to customize your color theme.',
     invalid_theme_imported: 'The selected file is not a supported Pleroma theme. No changes to your theme were made.',
     radii_help: 'Set up interface edge rounding (in pixels)',
@@ -1641,8 +1641,8 @@ const ru = {
     set_new_profile_background: 'Загрузить новый фон профиля',
     settings: 'Настройки',
     theme: 'Тема',
-    export_theme: 'Экспортировать текущую тему',
-    import_theme: 'Загрузить сохранённую тему',
+    export_theme: 'Сохранить Тему',
+    import_theme: 'Загрузить Тему',
     presets: 'Пресеты',
     theme_help: 'Используйте шестнадцатеричные коды цветов (#rrggbb) для настройки темы.',
     radii_help: 'Округление краёв элементов интерфейса (в пикселях)',
-- 
cgit v1.2.3-70-g09d2


From c3b27ab4c2d6ca03d8bea171735521b770172104 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 28 Aug 2018 15:47:42 +0300
Subject: moved replies filtering to "filter" category in settings, made it
 more consistent

---
 src/components/settings/settings.vue | 21 +++++++++++----------
 src/i18n/messages.js                 |  5 +++++
 2 files changed, 16 insertions(+), 10 deletions(-)

(limited to 'src/components/settings/settings.vue')

diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index 240cd70a..2f70c209 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -35,16 +35,6 @@
               <input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal">
               <label for="hoverPreview">{{$t('settings.reply_link_preview')}}</label>
             </li>
-            <li>
-              <label for="replyVisibility" class="select">
-                <select id="replyVisibility" v-model="replyVisibilityLocal">
-                  <option value="all" selected>{{$t('settings.reply_visibility_all')}}</option>
-                  <option value="following">{{$t('settings.reply_visibility_following')}}</option>
-                  <option value="self">{{$t('settings.reply_visibility_self')}}</option>
-                </select>
-                <i class="icon-down-open"/>
-              </label>
-            </li>
           </ul>
         </div>
         <div class="setting-item">
@@ -90,6 +80,17 @@
       </div>
 
       <div :title="$t('settings.filtering')" >
+        <div class="setting-item">
+          {{$t('settings.replies_in_timeline')}}
+          <label for="replyVisibility" class="select">
+            <select id="replyVisibility" v-model="replyVisibilityLocal">
+              <option value="all" selected>{{$t('settings.reply_visibility_all')}}</option>
+              <option value="following">{{$t('settings.reply_visibility_following')}}</option>
+              <option value="self">{{$t('settings.reply_visibility_self')}}</option>
+            </select>
+            <i class="icon-down-open"/>
+          </label>
+        </div>
         <div class="setting-item">
           <p>{{$t('settings.filtering_explanation')}}</p>
           <textarea id="muteWords" v-model="muteWordsString"></textarea>
diff --git a/src/i18n/messages.js b/src/i18n/messages.js
index cccf48cc..ebc96e81 100644
--- a/src/i18n/messages.js
+++ b/src/i18n/messages.js
@@ -327,6 +327,7 @@ const en = {
     loop_video: 'Loop videos',
     loop_video_silent_only: 'Loop only videos without sound (i.e. Mastodon\'s "gifs")',
     reply_link_preview: 'Enable reply-link preview on mouse hover',
+    replies_in_timeline: 'Replies in timeline',
     reply_visibility_all: 'Show all replies',
     reply_visibility_following: 'Only show replies directed at me or users I\'m following',
     reply_visibility_self: 'Only show replies directed at me',
@@ -1674,6 +1675,10 @@ const ru = {
     loop_video: 'Зациливать видео',
     loop_video_silent_only: 'Зацикливать только беззвучные видео (т.е. "гифки" с Mastodon)',
     reply_link_preview: 'Включить предварительный просмотр ответа при наведении мыши',
+    replies_in_timeline: 'Ответы в ленте',
+    reply_visibility_all: 'Показывать все ответы',
+    reply_visibility_following: 'Показывать только ответы мне и тех на кого я подписан',
+    reply_visibility_self: 'Показывать только ответы мне',
     follow_import: 'Импортировать читаемых',
     import_followers_from_a_csv_file: 'Импортировать читаемых из файла .csv',
     follows_imported: 'Список читаемых импортирован. Обработка займёт некоторое время..',
-- 
cgit v1.2.3-70-g09d2


From 66a22762c21f652342ca2421f732650c261abc02 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 28 Aug 2018 16:22:49 +0300
Subject: fixup! Separated tab-switcher into a reusable component. This depends
 on JSX addition

---
 src/components/settings/settings.vue           | 6 +++---
 src/components/tab_switcher/tab_switcher.jsx   | 2 +-
 src/components/user_settings/user_settings.vue | 6 +++---
 3 files changed, 7 insertions(+), 7 deletions(-)

(limited to 'src/components/settings/settings.vue')

diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index 2f70c209..c92602b7 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -5,7 +5,7 @@
   </div>
   <div class="panel-body">
     <tab-switcher>
-      <div :title="$t('settings.general')" >
+      <div :label="$t('settings.general')" >
         <div class="setting-item">
           <h2>{{ $t('settings.interfaceLanguage') }}</h2>
           <interface-language-switcher />
@@ -73,13 +73,13 @@
         </div>
       </div>
 
-      <div :title="$t('settings.theme')" >
+      <div :label="$t('settings.theme')" >
         <div class="setting-item">
           <style-switcher></style-switcher>
         </div>
       </div>
 
-      <div :title="$t('settings.filtering')" >
+      <div :label="$t('settings.filtering')" >
         <div class="setting-item">
           {{$t('settings.replies_in_timeline')}}
           <label for="replyVisibility" class="select">
diff --git a/src/components/tab_switcher/tab_switcher.jsx b/src/components/tab_switcher/tab_switcher.jsx
index 0a6eec11..3fff38f6 100644
--- a/src/components/tab_switcher/tab_switcher.jsx
+++ b/src/components/tab_switcher/tab_switcher.jsx
@@ -23,7 +23,7 @@ export default Vue.component('tab-switcher', {
             if (index === this.active) {
               classes.push('active')
             }
-            return (<button onClick={this.activateTab(index)} class={ classes.join(' ') }>{slot.data.attrs.title}</button>)
+            return (<button onClick={this.activateTab(index)} class={ classes.join(' ') }>{slot.data.attrs.label}</button>)
           });
     const contents = (
       <div>
diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue
index 64627d92..9daafdce 100644
--- a/src/components/user_settings/user_settings.vue
+++ b/src/components/user_settings/user_settings.vue
@@ -5,7 +5,7 @@
     </div>
     <div class="panel-body profile-edit">
       <tab-switcher>
-        <div :title="$t('settings.profile_tab')">
+        <div :label="$t('settings.profile_tab')">
           <div class="setting-item" >
             <h2>{{$t('settings.name_bio')}}</h2>
             <p>{{$t('settings.name')}}</p>
@@ -66,7 +66,7 @@
           </div>
         </div>
 
-        <div :title="$t('settings.security_tab')">
+        <div :label="$t('settings.security_tab')">
           <div class="setting-item">
             <h2>{{$t('settings.change_password')}}</h2>
             <div>
@@ -102,7 +102,7 @@
           </div>
         </div>
 
-        <div :title="$t('settings.data_import_export_tab')" v-if="pleromaBackend">
+        <div :label="$t('settings.data_import_export_tab')" v-if="pleromaBackend">
           <div class="setting-item">
             <h2>{{$t('settings.follow_import')}}</h2>
             <p>{{$t('settings.import_followers_from_a_csv_file')}}</p>
-- 
cgit v1.2.3-70-g09d2


From b0e0686c7f1084e7074feee509ad189c6010431b Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 28 Aug 2018 21:21:29 +0300
Subject: Added ability to hide certain types of notifications

---
 src/components/notifications/notifications.js | 12 ++++-
 src/components/settings/settings.js           | 13 ++++++
 src/components/settings/settings.vue          | 67 +++++++++++++++++++++++----
 src/i18n/messages.js                          | 10 ++++
 src/main.js                                   |  1 +
 src/modules/config.js                         |  6 +++
 src/modules/statuses.js                       | 18 +++++--
 7 files changed, 110 insertions(+), 17 deletions(-)

(limited to 'src/components/settings/settings.vue')

diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js
index b24250b0..58956f98 100644
--- a/src/components/notifications/notifications.js
+++ b/src/components/notifications/notifications.js
@@ -11,6 +11,14 @@ const Notifications = {
     notificationsFetcher.startFetching({ store, credentials })
   },
   computed: {
+    visibleTypes () {
+      return [
+        this.$store.state.config.notificationVisibility.likes && 'like',
+        this.$store.state.config.notificationVisibility.mentions && 'mention',
+        this.$store.state.config.notificationVisibility.repeats && 'repeat',
+        this.$store.state.config.notificationVisibility.follows && 'follow'
+      ].filter(_ => _)
+    },
     notifications () {
       return this.$store.state.statuses.notifications.data
     },
@@ -18,13 +26,13 @@ const Notifications = {
       return this.$store.state.statuses.notifications.error
     },
     unseenNotifications () {
-      return filter(this.notifications, ({seen}) => !seen)
+      return filter(this.visibleNotifications, ({seen}) => !seen)
     },
     visibleNotifications () {
       // Don't know why, but sortBy([seen, -action.id]) doesn't work.
       let sortedNotifications = sortBy(this.notifications, ({action}) => -action.id)
       sortedNotifications = sortBy(sortedNotifications, 'seen')
-      return sortedNotifications
+      return sortedNotifications.filter((notification) => this.visibleTypes.includes(notification.type))
     },
     unseenCount () {
       return this.unseenNotifications.length
diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js
index 333633c9..de12894b 100644
--- a/src/components/settings/settings.js
+++ b/src/components/settings/settings.js
@@ -10,6 +10,7 @@ const settings = {
       hideAttachmentsLocal: this.$store.state.config.hideAttachments,
       hideAttachmentsInConvLocal: this.$store.state.config.hideAttachmentsInConv,
       hideNsfwLocal: this.$store.state.config.hideNsfw,
+      notificationVisibilityLocal: this.$store.state.config.notificationVisibility,
       replyVisibilityLocal: this.$store.state.config.replyVisibility,
       loopVideoLocal: this.$store.state.config.loopVideo,
       loopVideoSilentOnlyLocal: this.$store.state.config.loopVideoSilentOnly,
@@ -49,6 +50,18 @@ const settings = {
     hideNsfwLocal (value) {
       this.$store.dispatch('setOption', { name: 'hideNsfw', value })
     },
+    'notificationVisibilityLocal.likes' (value) {
+      this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
+    },
+    'notificationVisibilityLocal.follows' (value) {
+      this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
+    },
+    'notificationVisibilityLocal.repeats' (value) {
+      this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
+    },
+    'notificationVisibilityLocal.mentions' (value) {
+      this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
+    },
     replyVisibilityLocal (value) {
       this.$store.dispatch('setOption', { name: 'replyVisibility', value })
     },
diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index c92602b7..dbc85f1f 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -81,15 +81,47 @@
 
       <div :label="$t('settings.filtering')" >
         <div class="setting-item">
-          {{$t('settings.replies_in_timeline')}}
-          <label for="replyVisibility" class="select">
-            <select id="replyVisibility" v-model="replyVisibilityLocal">
-              <option value="all" selected>{{$t('settings.reply_visibility_all')}}</option>
-              <option value="following">{{$t('settings.reply_visibility_following')}}</option>
-              <option value="self">{{$t('settings.reply_visibility_self')}}</option>
-            </select>
-            <i class="icon-down-open"/>
-          </label>
+          <div class="select-multiple">
+            <span class="label">{{$t('settings.notification_visibility')}}</span>
+            <ul class="option-list">
+              <li>
+                <input type="checkbox" id="notification-visibility-likes" v-model="notificationVisibilityLocal.likes">
+                <label for="notification-visibility-likes">
+                  {{$t('settings.notification_visibility_likes')}}
+                </label>
+              </li>
+              <li>
+                <input type="checkbox" id="notification-visibility-repeats" v-model="notificationVisibilityLocal.repeats">
+                <label for="notification-visibility-repeats">
+                {{$t('settings.notification_visibility_repeats')}}
+                </label>
+              </li>
+              <li>
+                <input type="checkbox" id="notification-visibility-follows" v-model="notificationVisibilityLocal.follows">
+                <label for="notification-visibility-follows">
+                {{$t('settings.notification_visibility_follows')}}
+                </label>
+              </li>
+              <li>
+                <input type="checkbox" id="notification-visibility-mentions" v-model="notificationVisibilityLocal.mentions">
+                <label for="notification-visibility-mentions">
+                {{$t('settings.notification_visibility_mentions')}}
+                </label>
+              </li>
+            </ul>
+            </label>
+          </div>
+          <div>
+            {{$t('settings.replies_in_timeline')}}
+            <label for="replyVisibility" class="select">
+              <select id="replyVisibility" v-model="replyVisibilityLocal">
+                <option value="all" selected>{{$t('settings.reply_visibility_all')}}</option>
+                <option value="following">{{$t('settings.reply_visibility_following')}}</option>
+                <option value="self">{{$t('settings.reply_visibility_self')}}</option>
+              </select>
+              <i class="icon-down-open"/>
+            </label>
+          </div>
         </div>
         <div class="setting-item">
           <p>{{$t('settings.filtering_explanation')}}</p>
@@ -113,6 +145,13 @@
   margin: 1em 1em 1.4em;
   padding-bottom: 1.4em;
 
+  div {
+    margin-bottom: .5em;
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+
   &:last-child {
     border-bottom: none;
     padding-bottom: 0;
@@ -159,7 +198,15 @@
     width: 10em;
   }
 }
-.setting-list {
+.select-multiple {
+  display: flex;
+  .option-list {
+    margin: 0;
+    padding-left: .5em;
+  }
+}
+.setting-list,
+.option-list{
   list-style-type: none;
   padding-left: 2em;
   li {
diff --git a/src/i18n/messages.js b/src/i18n/messages.js
index ebc96e81..08d81841 100644
--- a/src/i18n/messages.js
+++ b/src/i18n/messages.js
@@ -331,6 +331,11 @@ const en = {
     reply_visibility_all: 'Show all replies',
     reply_visibility_following: 'Only show replies directed at me or users I\'m following',
     reply_visibility_self: 'Only show replies directed at me',
+    notification_visibility: 'Types of notifications to show',
+    notification_visibility_likes: 'Likes',
+    notification_visibility_mentions: 'Mentions',
+    notification_visibility_repeats: 'Repeats',
+    notification_visibility_follows: 'Follows',
     follow_import: 'Follow import',
     import_followers_from_a_csv_file: 'Import follows from a csv file',
     follows_imported: 'Follows imported! Processing them will take a while.',
@@ -1679,6 +1684,11 @@ const ru = {
     reply_visibility_all: 'Показывать все ответы',
     reply_visibility_following: 'Показывать только ответы мне и тех на кого я подписан',
     reply_visibility_self: 'Показывать только ответы мне',
+    notification_visibility: 'Показывать уведомления',
+    notification_visibility_likes: 'Лайки',
+    notification_visibility_mentions: 'Упоминания',
+    notification_visibility_repeats: 'Повторы',
+    notification_visibility_follows: 'Подписки',
     follow_import: 'Импортировать читаемых',
     import_followers_from_a_csv_file: 'Импортировать читаемых из файла .csv',
     follows_imported: 'Список читаемых импортирован. Обработка займёт некоторое время..',
diff --git a/src/main.js b/src/main.js
index 5258fbd9..6c9bf36e 100644
--- a/src/main.js
+++ b/src/main.js
@@ -50,6 +50,7 @@ const persistedStateOptions = {
     'config.hideAttachmentsInConv',
     'config.hideNsfw',
     'config.replyVisibility',
+    'config.notificationVisibility',
     'config.autoLoad',
     'config.hoverPreview',
     'config.streaming',
diff --git a/src/modules/config.js b/src/modules/config.js
index ac163316..60a34bc1 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -18,6 +18,12 @@ const defaultState = {
   pauseOnUnfocused: true,
   stopGifs: false,
   replyVisibility: 'all',
+  notificationVisibility: {
+    follows: true,
+    mentions: true,
+    likes: true,
+    repeats: true
+  },
   muteWords: [],
   highlight: {},
   interfaceLanguage: browserLocale
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 0dd88266..c69c5be6 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -68,6 +68,15 @@ export const prepareStatus = (status) => {
   return status
 }
 
+const visibleNotificationTypes = (rootState) => {
+  return [
+    rootState.config.notificationVisibility.likes && 'like',
+    rootState.config.notificationVisibility.mentions && 'mention',
+    rootState.config.notificationVisibility.repeats && 'repeat',
+    rootState.config.notificationVisibility.follows && 'follow'
+  ].filter(_ => _)
+}
+
 export const statusType = (status) => {
   if (status.is_post_verb) {
     return 'status'
@@ -86,8 +95,7 @@ export const statusType = (status) => {
     return 'deletion'
   }
 
-  // TODO change to status.activity_type === 'follow' when gs supports it
-  if (status.text.match(/started following/)) {
+  if (status.text.match(/started following/) || status.activity_type === 'follow') {
     return 'follow'
   }
 
@@ -269,7 +277,7 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
   }
 }
 
-const addNewNotifications = (state, { dispatch, notifications, older }) => {
+const addNewNotifications = (state, { dispatch, notifications, older, visibleNotificationTypes }) => {
   const allStatuses = state.allStatuses
   const allStatusesObject = state.allStatusesObject
   each(notifications, (notification) => {
@@ -318,7 +326,7 @@ const addNewNotifications = (state, { dispatch, notifications, older }) => {
           result.image = action.attachments[0].url
         }
 
-        if (fresh && !state.notifications.desktopNotificationSilence) {
+        if (fresh && !state.notifications.desktopNotificationSilence && visibleNotificationTypes.includes(notification.ntype)) {
           let notification = new window.Notification(title, result)
           // Chrome is known for not closing notifications automatically
           // according to MDN, anyway.
@@ -405,7 +413,7 @@ const statuses = {
       commit('addNewStatuses', { statuses, showImmediately, timeline, noIdUpdate, user: rootState.users.currentUser })
     },
     addNewNotifications ({ rootState, commit, dispatch }, { notifications, older }) {
-      commit('addNewNotifications', { dispatch, notifications, older })
+      commit('addNewNotifications', { visibleNotificationTypes: visibleNotificationTypes(rootState), dispatch, notifications, older })
     },
     setError ({ rootState, commit }, { value }) {
       commit('setError', { value })
-- 
cgit v1.2.3-70-g09d2


From 3b9cb1384ae3ca667cb8301e95dabe7c5861226f Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 30 Aug 2018 19:53:13 +0300
Subject: fix

---
 src/components/settings/settings.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/components/settings/settings.vue')

diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index dbc85f1f..c106b79c 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -145,7 +145,7 @@
   margin: 1em 1em 1.4em;
   padding-bottom: 1.4em;
 
-  div {
+  > div {
     margin-bottom: .5em;
     &:last-child {
       margin-bottom: 0;
-- 
cgit v1.2.3-70-g09d2

