Browse Source

Add timed-mute functionality

Tusooa Zhu 2 years ago
parent
commit
228a9afdf5

+ 2 - 11
src/components/poll/poll_form.js

@@ -94,19 +94,10 @@ export default {
     },
     convertExpiryToUnit (unit, amount) {
       // Note: we want seconds and not milliseconds
-      switch (unit) {
-        case 'minutes': return (1000 * amount) / DateUtils.MINUTE
-        case 'hours': return (1000 * amount) / DateUtils.HOUR
-        case 'days': return (1000 * amount) / DateUtils.DAY
-      }
+      return DateUtils.secondsToUnit(unit, amount)
     },
     convertExpiryFromUnit (unit, amount) {
-      // Note: we want seconds and not milliseconds
-      switch (unit) {
-        case 'minutes': return 0.001 * amount * DateUtils.MINUTE
-        case 'hours': return 0.001 * amount * DateUtils.HOUR
-        case 'days': return 0.001 * amount * DateUtils.DAY
-      }
+      return DateUtils.unitToSeconds(unit, amount)
     },
     expiryAmountChange () {
       this.expiryAmount =

+ 11 - 2
src/components/user_card/user_card.js

@@ -1,3 +1,4 @@
+import { unitToSeconds } from 'src/services/date_utils/date_utils.js'
 import UserAvatar from '../user_avatar/user_avatar.vue'
 import RemoteFollow from '../remote_follow/remote_follow.vue'
 import ProgressButton from '../progress_button/progress_button.vue'
@@ -48,7 +49,9 @@ export default {
     return {
       followRequestInProgress: false,
       betterShadow: this.$store.state.interface.browserSupport.cssFilter,
-      showingConfirmMute: false
+      showingConfirmMute: false,
+      muteExpiryAmount: 0,
+      muteExpiryUnit: 'minutes'
     }
   },
   created () {
@@ -142,6 +145,9 @@ export default {
     shouldConfirmMute () {
       return this.mergedConfig.modalOnMute
     },
+    muteExpiryUnits () {
+      return ['minutes', 'hours', 'days']
+    },
     ...mapGetters(['mergedConfig'])
   },
   components: {
@@ -172,7 +178,10 @@ export default {
       }
     },
     doMuteUser () {
-      this.$store.dispatch('muteUser', this.user.id)
+      this.$store.dispatch('muteUser', {
+        id: this.user.id,
+        expiresIn: this.shouldConfirmMute ? unitToSeconds(this.muteExpiryUnit, this.muteExpiryAmount) : 0
+      })
       this.hideConfirmMute()
     },
     unmuteUser () {

+ 5 - 0
src/components/user_card/user_card.scss

@@ -355,3 +355,8 @@
     text-decoration: none;
   }
 }
+
+.mute-expiry {
+  display: flex;
+  flex-direction: row;
+}

+ 27 - 1
src/components/user_card/user_card.vue

@@ -325,7 +325,7 @@
       >
         <i18n-t
           keypath="user_card.mute_confirm"
-          tag="span"
+          tag="div"
         >
           <template #user>
             <span
@@ -333,6 +333,32 @@
             />
           </template>
         </i18n-t>
+        <div
+          class="mute-expiry"
+        >
+          <label>
+            {{ $t('user_card.mute_duration_prompt') }}
+          </label>
+          <input
+            v-model="muteExpiryAmount"
+            type="number"
+            class="expiry-amount hide-number-spinner"
+            :min="0"
+          >
+          <Select
+            v-model="muteExpiryUnit"
+            unstyled="true"
+            class="expiry-unit"
+          >
+            <option
+              v-for="unit in muteExpiryUnits"
+              :key="unit"
+              :value="unit"
+            >
+              {{ $t(`time.${unit}_short`, ['']) }}
+            </option>
+          </Select>
+        </div>
       </confirm-modal>
     </teleport>
   </div>

+ 5 - 2
src/modules/users.js

@@ -61,13 +61,16 @@ const editUserNote = (store, { id, comment }) => {
     .then((relationship) => store.commit('updateUserRelationship', [relationship]))
 }
 
-const muteUser = (store, id) => {
+const muteUser = (store, args) => {
+  const id = typeof args === 'object' ? args.id : args
+  const expiresIn = typeof args === 'object' ? args.expiresIn : 0
+
   const predictedRelationship = store.state.relationships[id] || { id }
   predictedRelationship.muting = true
   store.commit('updateUserRelationship', [predictedRelationship])
   store.commit('addMuteId', id)
 
-  return store.rootState.api.backendInteractor.muteUser({ id })
+  return store.rootState.api.backendInteractor.muteUser({ id, expiresIn })
     .then((relationship) => {
       store.commit('updateUserRelationship', [relationship])
       store.commit('addMuteId', id)

+ 6 - 2
src/services/api/api.service.js

@@ -1118,8 +1118,12 @@ const fetchMutes = ({ credentials }) => {
     .then((users) => users.map(parseUser))
 }
 
-const muteUser = ({ id, credentials }) => {
-  return promisedRequest({ url: MASTODON_MUTE_USER_URL(id), credentials, method: 'POST' })
+const muteUser = ({ id, expiresIn, credentials }) => {
+  const payload = {}
+  if (expiresIn) {
+    payload['expires_in'] = expiresIn
+  }
+  return promisedRequest({ url: MASTODON_MUTE_USER_URL(id), credentials, method: 'POST', payload })
 }
 
 const unmuteUser = ({ id, credentials }) => {

+ 16 - 0
src/services/date_utils/date_utils.js

@@ -41,3 +41,19 @@ export const relativeTimeShort = (date, nowThreshold = 1) => {
   r.key += '_short'
   return r
 }
+
+export const unitToSeconds = (unit, amount) => {
+  switch (unit) {
+    case 'minutes': return 0.001 * amount * MINUTE
+    case 'hours': return 0.001 * amount * HOUR
+    case 'days': return 0.001 * amount * DAY
+  }
+}
+
+export const secondsToUnit = (unit, amount) => {
+  switch (unit) {
+    case 'minutes': return (1000 * amount) / MINUTE
+    case 'hours': return (1000 * amount) / HOUR
+    case 'days': return (1000 * amount) / DAY
+  }
+}