feat: record audio button
Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
parent
b074e9c58e
commit
c0c0742687
|
@ -0,0 +1,18 @@
|
||||||
|
import { useDerivedValue } from 'react-native-reanimated';
|
||||||
|
|
||||||
|
const MAX_SCALE = 1.8;
|
||||||
|
|
||||||
|
export function ringScale(scale, subtract) {
|
||||||
|
return useDerivedValue(
|
||||||
|
function () {
|
||||||
|
'worklet'
|
||||||
|
const value = scale.value;
|
||||||
|
const maxDelta = MAX_SCALE - 1;
|
||||||
|
const maxDeltaDiff = 1 - maxDelta;
|
||||||
|
const maxVirtualScale = MAX_SCALE + maxDelta;
|
||||||
|
const decimals = value - Math.floor(value);
|
||||||
|
const normalizedValue = value >= maxVirtualScale ? (decimals + ((parseInt(value) - 1) * maxDeltaDiff) + 1) : value;
|
||||||
|
return (((normalizedValue - subtract) > MAX_SCALE ? normalizedValue - maxDelta : normalizedValue) - subtract);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { useDerivedValue, interpolate } from 'react-native-reanimated';
|
||||||
|
|
||||||
// Generic Worklets
|
// Generic Worklets
|
||||||
|
|
||||||
export function applyAnimationsToStyle(animations, style) {
|
export function applyAnimationsToStyle(animations, style) {
|
||||||
|
@ -27,3 +29,12 @@ export function applyAnimationsToStyle(animations, style) {
|
||||||
return Object.assign(animatedStyle, style);
|
return Object.assign(animatedStyle, style);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function interpolateValue(sharedValue, inputRange, outputRange) {
|
||||||
|
return useDerivedValue(
|
||||||
|
function () {
|
||||||
|
'worklet'
|
||||||
|
return interpolate(sharedValue.value, inputRange, outputRange);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -284,6 +284,8 @@
|
||||||
|
|
||||||
(def shell-worklets #js {})
|
(def shell-worklets #js {})
|
||||||
|
|
||||||
|
(def record-audio-worklets #js {})
|
||||||
|
|
||||||
;; Update i18n_resources.cljs
|
;; Update i18n_resources.cljs
|
||||||
(defn mock [module]
|
(defn mock [module]
|
||||||
(case module
|
(case module
|
||||||
|
@ -331,6 +333,7 @@
|
||||||
"react-native-svg" react-native-svg
|
"react-native-svg" react-native-svg
|
||||||
"../src/js/worklet_factory.js" worklet-factory
|
"../src/js/worklet_factory.js" worklet-factory
|
||||||
"../src/js/shell_worklets.js" shell-worklets
|
"../src/js/shell_worklets.js" shell-worklets
|
||||||
|
"../src/js/record_audio_worklets.js" record-audio-worklets
|
||||||
"./fleets.js" default-fleets
|
"./fleets.js" default-fleets
|
||||||
"./chats.js" default-chats
|
"./chats.js" default-chats
|
||||||
"@walletconnect/client" wallet-connect-client
|
"@walletconnect/client" wallet-connect-client
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
(ns quo2.components.record-audio.record-audio.style
|
||||||
|
(:require [quo2.foundations.colors :as colors]
|
||||||
|
[react-native.reanimated :as reanimated]))
|
||||||
|
|
||||||
|
(defn animated-circle [scale opacity color]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:transform [{:scale scale}]
|
||||||
|
:opacity opacity}
|
||||||
|
{:width 56
|
||||||
|
:height 56
|
||||||
|
:border-width 1
|
||||||
|
:border-color color
|
||||||
|
:border-radius 28
|
||||||
|
:position :absolute
|
||||||
|
:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:z-index 0}))
|
||||||
|
|
||||||
|
(defn record-button-big-container [translate-x translate-y opacity]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:transform [{:translateY translate-y}
|
||||||
|
{:translateX translate-x}]
|
||||||
|
:opacity opacity}
|
||||||
|
{:position :absolute
|
||||||
|
:bottom 0
|
||||||
|
:right 0
|
||||||
|
:width 96
|
||||||
|
:height 96
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :center
|
||||||
|
:z-index 0}))
|
||||||
|
|
||||||
|
(defn record-button-big-body [button-color]
|
||||||
|
{:width 56
|
||||||
|
:height 56
|
||||||
|
:border-radius 28
|
||||||
|
:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:background-color button-color
|
||||||
|
:overflow :hidden})
|
||||||
|
|
||||||
|
(defn record-button-big-red-overlay [red-overlay-opacity]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:opacity red-overlay-opacity}
|
||||||
|
{:position :absolute
|
||||||
|
:top 0
|
||||||
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:bottom 0
|
||||||
|
:background-color colors/danger-50}))
|
||||||
|
|
||||||
|
(defn record-button-big-gray-overlay [gray-overlay-opacity]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:opacity gray-overlay-opacity}
|
||||||
|
{:position :absolute
|
||||||
|
:top 0
|
||||||
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:bottom 0
|
||||||
|
:background-color (colors/theme-colors colors/neutral-80-opa-5-opaque colors/neutral-80)}))
|
||||||
|
|
||||||
|
(defn record-button-big-icon-container [icon-opacity]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:opacity icon-opacity}
|
||||||
|
{}))
|
||||||
|
|
||||||
|
(def stop-icon
|
||||||
|
{:width 13
|
||||||
|
:height 13
|
||||||
|
:border-radius 4
|
||||||
|
:background-color colors/white})
|
||||||
|
|
||||||
|
(defn send-button-container [opacity]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:opacity opacity}
|
||||||
|
{:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:position :absolute
|
||||||
|
:width 56
|
||||||
|
:height 56
|
||||||
|
:top 0
|
||||||
|
:right 20}))
|
||||||
|
|
||||||
|
(defn send-button-connector [opacity width height border-radius-first-half border-radius-second-half]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:opacity opacity
|
||||||
|
:width width
|
||||||
|
:height height
|
||||||
|
:border-bottom-left-radius border-radius-second-half
|
||||||
|
:border-top-left-radius border-radius-first-half
|
||||||
|
:border-top-right-radius border-radius-first-half
|
||||||
|
:border-bottom-right-radius border-radius-second-half}
|
||||||
|
{:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:align-self :center
|
||||||
|
:background-color colors/primary-50
|
||||||
|
:z-index 0}))
|
||||||
|
|
||||||
|
(defn send-button [translate-y opacity]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:transform [{:translateY translate-y}]
|
||||||
|
:opacity opacity}
|
||||||
|
{:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:background-color colors/primary-50
|
||||||
|
:width 32
|
||||||
|
:height 32
|
||||||
|
:border-radius 16
|
||||||
|
:position :absolute
|
||||||
|
:top 0
|
||||||
|
:right 32
|
||||||
|
:z-index 10}))
|
||||||
|
|
||||||
|
(def send-icon-container
|
||||||
|
{:z-index 10})
|
||||||
|
|
||||||
|
(defn lock-button-container [opacity]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:opacity opacity}
|
||||||
|
{:transform [{:rotate "45deg"}]
|
||||||
|
:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:position :absolute
|
||||||
|
:width 56
|
||||||
|
:height 56
|
||||||
|
:top 20
|
||||||
|
:left 20}))
|
||||||
|
|
||||||
|
(defn lock-button-connector [opacity width height border-radius-first-half border-radius-second-half]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:opacity opacity
|
||||||
|
:width width
|
||||||
|
:height height
|
||||||
|
:border-bottom-left-radius border-radius-first-half
|
||||||
|
:border-top-left-radius border-radius-first-half
|
||||||
|
:border-top-right-radius border-radius-second-half
|
||||||
|
:border-bottom-right-radius border-radius-second-half}
|
||||||
|
{:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:align-self :center
|
||||||
|
:background-color (colors/theme-colors colors/neutral-80-opa-5-opaque colors/neutral-80)
|
||||||
|
:overflow :hidden}))
|
||||||
|
|
||||||
|
(defn lock-button [translate-x-y opacity]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:transform [{:translateX translate-x-y}
|
||||||
|
{:translateY translate-x-y}]
|
||||||
|
:opacity opacity}
|
||||||
|
{:width 32
|
||||||
|
:height 32
|
||||||
|
:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:background-color (colors/theme-colors colors/neutral-80-opa-5-opaque colors/neutral-80)
|
||||||
|
:border-radius 16
|
||||||
|
:position :absolute
|
||||||
|
:top 24
|
||||||
|
:left 24
|
||||||
|
:overflow :hidden
|
||||||
|
:z-index 12}))
|
||||||
|
|
||||||
|
(defn delete-button-container [opacity]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:opacity opacity}
|
||||||
|
{:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:position :absolute
|
||||||
|
:width 56
|
||||||
|
:height 56
|
||||||
|
:bottom 20
|
||||||
|
:left 0}))
|
||||||
|
|
||||||
|
(defn delete-button-connector [opacity width height border-radius-first-half border-radius-second-half]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:opacity opacity
|
||||||
|
:width width
|
||||||
|
:height height
|
||||||
|
:border-bottom-left-radius border-radius-first-half
|
||||||
|
:border-top-left-radius border-radius-first-half
|
||||||
|
:border-top-right-radius border-radius-second-half
|
||||||
|
:border-bottom-right-radius border-radius-second-half}
|
||||||
|
{:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:align-self :center
|
||||||
|
:background-color colors/danger-50
|
||||||
|
:z-index 0}))
|
||||||
|
|
||||||
|
(defn delete-button [translate-x opacity]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:transform [{:translateX translate-x}]
|
||||||
|
:opacity opacity}
|
||||||
|
{:width 32
|
||||||
|
:height 32
|
||||||
|
:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:background-color colors/danger-50
|
||||||
|
:border-radius 16
|
||||||
|
:position :absolute
|
||||||
|
:top 76
|
||||||
|
:left 0
|
||||||
|
:z-index 11}))
|
||||||
|
|
||||||
|
(defn record-button-container [opacity]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:opacity opacity}
|
||||||
|
{:margin-bottom 32
|
||||||
|
:margin-right 32}))
|
||||||
|
|
||||||
|
(def input-container
|
||||||
|
{:width 140
|
||||||
|
:height 140
|
||||||
|
:align-items :flex-end
|
||||||
|
:justify-content :flex-end})
|
|
@ -0,0 +1,553 @@
|
||||||
|
(ns quo2.components.record-audio.record-audio.view
|
||||||
|
(:require [quo.react :refer [memo effect!]]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[quo2.components.icon :as icons]
|
||||||
|
[quo2.components.buttons.button :as button]
|
||||||
|
[react-native.reanimated :as reanimated]
|
||||||
|
[reagent.core :as reagent]
|
||||||
|
[cljs-bean.core :as bean]
|
||||||
|
[quo2.components.record-audio.record-audio.style :as style]
|
||||||
|
[status-im.utils.utils :as utils]
|
||||||
|
[oops.core :as oops]))
|
||||||
|
|
||||||
|
(def ^:private scale-to-each 1.8)
|
||||||
|
(def ^:private scale-to-total 2.6)
|
||||||
|
(def ^:private scale-padding 0.16)
|
||||||
|
(def ^:private opacity-from-lock 1)
|
||||||
|
(def ^:private opacity-from-default 0.5)
|
||||||
|
(def ^:private signal-anim-duration 3900)
|
||||||
|
(def ^:private signal-anim-duration-2 1950)
|
||||||
|
|
||||||
|
(def ^:private animated-ring
|
||||||
|
(reagent/adapt-react-class
|
||||||
|
(memo
|
||||||
|
(fn [props]
|
||||||
|
(let [{:keys [scale opacity color]} (bean/bean props)]
|
||||||
|
(reagent/as-element
|
||||||
|
[reanimated/view {:style (style/animated-circle scale opacity color)}]))))))
|
||||||
|
|
||||||
|
(def ^:private record-button-area-big
|
||||||
|
{:width 56
|
||||||
|
:height 56
|
||||||
|
:x 64
|
||||||
|
:y 64})
|
||||||
|
|
||||||
|
(def ^:private record-button-area
|
||||||
|
{:width 48
|
||||||
|
:height 48
|
||||||
|
:x 68
|
||||||
|
:y 68})
|
||||||
|
|
||||||
|
(defn- delete-button-area [active?]
|
||||||
|
{:width (if active? 72 82)
|
||||||
|
:height 56
|
||||||
|
:x (if active? -16 -32)
|
||||||
|
:y (if active? 64 70)})
|
||||||
|
|
||||||
|
(defn- lock-button-area [active?]
|
||||||
|
{:width (if active? 72 100)
|
||||||
|
:height (if active? 72 102)
|
||||||
|
:x -32
|
||||||
|
:y -32})
|
||||||
|
|
||||||
|
(defn- send-button-area [active?]
|
||||||
|
{:width 56
|
||||||
|
:height (if active? 72 92)
|
||||||
|
:x 68
|
||||||
|
:y (if active? -16 -32)})
|
||||||
|
|
||||||
|
(defn- touch-inside-area? [{:keys [location-x location-y ignore-min-y? ignore-max-y? ignore-min-x? ignore-max-x?]}
|
||||||
|
{:keys [width height x y]}]
|
||||||
|
(let [max-x (+ x width)
|
||||||
|
max-y (+ y height)]
|
||||||
|
(and
|
||||||
|
(and
|
||||||
|
(or ignore-min-x? (>= location-x x))
|
||||||
|
(or ignore-max-x? (<= location-x max-x)))
|
||||||
|
(and
|
||||||
|
(or ignore-min-y? (>= location-y y))
|
||||||
|
(or ignore-max-y? (<= location-y max-y))))))
|
||||||
|
|
||||||
|
(def record-audio-worklets (js/require "../src/js/record_audio_worklets.js"))
|
||||||
|
|
||||||
|
(defn- ring-scale [scale substract]
|
||||||
|
(.ringScale ^js record-audio-worklets
|
||||||
|
scale
|
||||||
|
substract))
|
||||||
|
|
||||||
|
(defn- record-button-big [recording? ready-to-send? ready-to-lock? ready-to-delete? record-button-is-animating? record-button-at-initial-position? locked? reviewing-audio? recording-timer recording-length-ms clear-timeout touch-active?]
|
||||||
|
[:f>
|
||||||
|
(fn []
|
||||||
|
(let [scale (reanimated/use-shared-value 1)
|
||||||
|
opacity (reanimated/use-shared-value 0)
|
||||||
|
opacity-from (if @ready-to-lock? opacity-from-lock opacity-from-default)
|
||||||
|
animations (map
|
||||||
|
(fn [index]
|
||||||
|
(let [ring-scale (ring-scale scale (* scale-padding index))]
|
||||||
|
{:scale ring-scale
|
||||||
|
:opacity (reanimated/interpolate ring-scale [1 scale-to-each] [opacity-from 0])}))
|
||||||
|
(range 0 5))
|
||||||
|
rings-color (cond
|
||||||
|
@ready-to-lock? (colors/theme-colors colors/neutral-80-opa-5-opaque colors/neutral-80)
|
||||||
|
@ready-to-delete? colors/danger-50
|
||||||
|
:else colors/primary-50)
|
||||||
|
translate-y (reanimated/use-shared-value 0)
|
||||||
|
translate-x (reanimated/use-shared-value 0)
|
||||||
|
button-color colors/primary-50
|
||||||
|
icon-color (if (and (not (colors/dark?)) @ready-to-lock?) colors/black colors/white)
|
||||||
|
icon-opacity (reanimated/use-shared-value 1)
|
||||||
|
red-overlay-opacity (reanimated/use-shared-value 0)
|
||||||
|
gray-overlay-opacity (reanimated/use-shared-value 0)
|
||||||
|
complete-animation (fn []
|
||||||
|
(cond
|
||||||
|
(and @ready-to-lock? (not @record-button-is-animating?))
|
||||||
|
(do
|
||||||
|
(reset! locked? true)
|
||||||
|
(reset! ready-to-lock? false))
|
||||||
|
(and (not @locked?) (not @reviewing-audio?))
|
||||||
|
(do
|
||||||
|
(reset! recording? false)
|
||||||
|
(reset! ready-to-send? false)
|
||||||
|
(reset! ready-to-delete? false)
|
||||||
|
(reset! ready-to-lock? false)
|
||||||
|
(utils/clear-interval @recording-timer)
|
||||||
|
(reset! recording-length-ms 0))))
|
||||||
|
start-animation (fn []
|
||||||
|
(reanimated/set-shared-value opacity 1)
|
||||||
|
(reanimated/animate-shared-value-with-timing scale 2.6 signal-anim-duration :linear)
|
||||||
|
;; TODO: Research if we can implement this with withSequence method from Reanimated 2
|
||||||
|
;; GitHub issue [#14561]: https://github.com/status-im/status-mobile/issues/14561
|
||||||
|
(reset! clear-timeout (utils/set-timeout #(do (reanimated/set-shared-value scale scale-to-each)
|
||||||
|
(reanimated/animate-shared-value-with-delay-repeat scale scale-to-total signal-anim-duration-2 :linear 0 -1))
|
||||||
|
signal-anim-duration)))
|
||||||
|
stop-animation (fn []
|
||||||
|
(reanimated/set-shared-value opacity 0)
|
||||||
|
(reanimated/cancel-animation scale)
|
||||||
|
(reanimated/set-shared-value scale 1)
|
||||||
|
(when @clear-timeout (utils/clear-timeout @clear-timeout)))
|
||||||
|
start-y-animation (fn []
|
||||||
|
(reset! record-button-at-initial-position? false)
|
||||||
|
(reset! record-button-is-animating? true)
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-y -64 250 :easing1)
|
||||||
|
(reanimated/animate-shared-value-with-delay icon-opacity 0 33.33 :linear 76.66)
|
||||||
|
(utils/set-timeout (fn []
|
||||||
|
(reset! record-button-is-animating? false)
|
||||||
|
(when-not @touch-active? (complete-animation)))
|
||||||
|
250))
|
||||||
|
reset-y-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-y 0 300 :easing1)
|
||||||
|
(reanimated/animate-shared-value-with-timing icon-opacity 1 500 :linear)
|
||||||
|
(utils/set-timeout (fn [] (reset! record-button-at-initial-position? true)) 500))
|
||||||
|
start-x-animation (fn []
|
||||||
|
(reset! record-button-at-initial-position? false)
|
||||||
|
(reset! record-button-is-animating? true)
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-x -64 250 :easing1)
|
||||||
|
(reanimated/animate-shared-value-with-delay icon-opacity 0 33.33 :linear 76.66)
|
||||||
|
(reanimated/animate-shared-value-with-timing red-overlay-opacity 1 33.33 :linear)
|
||||||
|
(utils/set-timeout (fn []
|
||||||
|
(reset! record-button-is-animating? false)
|
||||||
|
(when-not @touch-active? (complete-animation)))
|
||||||
|
250))
|
||||||
|
reset-x-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-x 0 300 :easing1)
|
||||||
|
(reanimated/animate-shared-value-with-timing icon-opacity 1 500 :linear)
|
||||||
|
(reanimated/animate-shared-value-with-timing red-overlay-opacity 0 100 :linear)
|
||||||
|
(utils/set-timeout (fn [] (reset! record-button-at-initial-position? true)) 500))
|
||||||
|
start-x-y-animation (fn []
|
||||||
|
(reset! record-button-at-initial-position? false)
|
||||||
|
(reset! record-button-is-animating? true)
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-y -44 200 :easing1)
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-x -44 200 :easing1)
|
||||||
|
(reanimated/animate-shared-value-with-delay icon-opacity 0 33.33 :linear 33.33)
|
||||||
|
(reanimated/animate-shared-value-with-timing gray-overlay-opacity 1 33.33 :linear)
|
||||||
|
(utils/set-timeout (fn []
|
||||||
|
(reset! record-button-is-animating? false)
|
||||||
|
(when-not @touch-active? (complete-animation)))
|
||||||
|
200))
|
||||||
|
reset-x-y-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-y 0 300 :easing1)
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-x 0 300 :easing1)
|
||||||
|
(reanimated/animate-shared-value-with-timing icon-opacity 1 500 :linear)
|
||||||
|
(reanimated/animate-shared-value-with-timing gray-overlay-opacity 0 800 :linear)
|
||||||
|
(utils/set-timeout (fn [] (reset! record-button-at-initial-position? true)) 800))]
|
||||||
|
(effect! #(cond
|
||||||
|
@recording?
|
||||||
|
(start-animation)
|
||||||
|
(not @ready-to-lock?)
|
||||||
|
(stop-animation))
|
||||||
|
[@recording?])
|
||||||
|
(effect! #(if @ready-to-lock?
|
||||||
|
(start-x-y-animation)
|
||||||
|
(reset-x-y-animation))
|
||||||
|
[@ready-to-lock?])
|
||||||
|
(effect! #(if @ready-to-send?
|
||||||
|
(start-y-animation)
|
||||||
|
(reset-y-animation))
|
||||||
|
[@ready-to-send?])
|
||||||
|
(effect! #(if @ready-to-delete?
|
||||||
|
(start-x-animation)
|
||||||
|
(reset-x-animation))
|
||||||
|
[@ready-to-delete?])
|
||||||
|
[reanimated/view {:style (style/record-button-big-container translate-x translate-y opacity)
|
||||||
|
:pointer-events :none}
|
||||||
|
[:<>
|
||||||
|
(map-indexed
|
||||||
|
(fn [id animation]
|
||||||
|
^{:key id}
|
||||||
|
[animated-ring {:scale (:scale animation)
|
||||||
|
:opacity (:opacity animation)
|
||||||
|
:color rings-color}])
|
||||||
|
animations)]
|
||||||
|
[rn/view {:style (style/record-button-big-body button-color)}
|
||||||
|
[reanimated/view {:style (style/record-button-big-red-overlay red-overlay-opacity)}]
|
||||||
|
[reanimated/view {:style (style/record-button-big-gray-overlay gray-overlay-opacity)}]
|
||||||
|
[reanimated/view {:style (style/record-button-big-icon-container icon-opacity)}
|
||||||
|
(if @locked?
|
||||||
|
[rn/view {:style style/stop-icon}]
|
||||||
|
[icons/icon :i/audio {:color icon-color}])]]]))])
|
||||||
|
|
||||||
|
(defn- send-button [recording? ready-to-send? reviewing-audio?]
|
||||||
|
[:f>
|
||||||
|
(fn []
|
||||||
|
(let [opacity (reanimated/use-shared-value 0)
|
||||||
|
translate-y (reanimated/use-shared-value 20)
|
||||||
|
connector-opacity (reanimated/use-shared-value 0)
|
||||||
|
width (reanimated/use-shared-value 12)
|
||||||
|
height (reanimated/use-shared-value 24)
|
||||||
|
border-radius-first-half (reanimated/use-shared-value 16)
|
||||||
|
border-radius-second-half (reanimated/use-shared-value 8)
|
||||||
|
start-y-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-delay translate-y 12 50 :linear 133.33)
|
||||||
|
(reanimated/animate-shared-value-with-delay connector-opacity 1 0 :easing1 93.33)
|
||||||
|
(reanimated/animate-shared-value-with-delay width 56 83.33 :easing1 80)
|
||||||
|
(reanimated/animate-shared-value-with-delay height 56 83.33 :easing1 80)
|
||||||
|
(reanimated/animate-shared-value-with-delay border-radius-first-half 28 83.33 :easing1 80)
|
||||||
|
(reanimated/animate-shared-value-with-delay border-radius-second-half 28 83.33 :easing1 80))
|
||||||
|
reset-y-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-y 0 100 :linear)
|
||||||
|
(reanimated/set-shared-value connector-opacity 0)
|
||||||
|
(reanimated/set-shared-value width 12)
|
||||||
|
(reanimated/set-shared-value height 24)
|
||||||
|
(reanimated/set-shared-value border-radius-first-half 16)
|
||||||
|
(reanimated/set-shared-value border-radius-second-half 8))
|
||||||
|
fade-in-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-y 0 200 :linear)
|
||||||
|
(reanimated/animate-shared-value-with-timing opacity 1 200 :linear))
|
||||||
|
fade-out-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-y (if @reviewing-audio? 76 20) 200 :linear)
|
||||||
|
(when-not @reviewing-audio? (reanimated/animate-shared-value-with-timing opacity 0 200 :linear))
|
||||||
|
(reanimated/set-shared-value connector-opacity 0)
|
||||||
|
(reanimated/set-shared-value width 24)
|
||||||
|
(reanimated/set-shared-value height 12)
|
||||||
|
(reanimated/set-shared-value border-radius-first-half 8)
|
||||||
|
(reanimated/set-shared-value border-radius-second-half 16))
|
||||||
|
fade-out-reset-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-timing opacity 0 200 :linear)
|
||||||
|
(reanimated/animate-shared-value-with-delay translate-y 20 0 :linear 200)
|
||||||
|
(reanimated/set-shared-value connector-opacity 0)
|
||||||
|
(reanimated/set-shared-value width 24)
|
||||||
|
(reanimated/set-shared-value height 12)
|
||||||
|
(reanimated/set-shared-value border-radius-first-half 8)
|
||||||
|
(reanimated/set-shared-value border-radius-second-half 16))]
|
||||||
|
(effect! #(if @recording?
|
||||||
|
(fade-in-animation)
|
||||||
|
(fade-out-animation))
|
||||||
|
[@recording?])
|
||||||
|
(effect! #(when-not @reviewing-audio?
|
||||||
|
(fade-out-reset-animation))
|
||||||
|
[@reviewing-audio?])
|
||||||
|
(effect! #(cond
|
||||||
|
@ready-to-send?
|
||||||
|
(start-y-animation)
|
||||||
|
@recording? (reset-y-animation))
|
||||||
|
[@ready-to-send?])
|
||||||
|
[:<>
|
||||||
|
[reanimated/view {:style (style/send-button-container opacity)}
|
||||||
|
[reanimated/view {:style (style/send-button-connector connector-opacity width height border-radius-first-half border-radius-second-half)}]]
|
||||||
|
[reanimated/view {:style (style/send-button translate-y opacity)
|
||||||
|
:pointer-events :none}
|
||||||
|
[icons/icon :i/arrow-up {:color colors/white
|
||||||
|
:size 20
|
||||||
|
:container-style style/send-icon-container}]]]))])
|
||||||
|
|
||||||
|
(defn- lock-button [recording? ready-to-lock? locked?]
|
||||||
|
[:f>
|
||||||
|
(fn []
|
||||||
|
(let [translate-x-y (reanimated/use-shared-value 20)
|
||||||
|
opacity (reanimated/use-shared-value 0)
|
||||||
|
connector-opacity (reanimated/use-shared-value 0)
|
||||||
|
width (reanimated/use-shared-value 24)
|
||||||
|
height (reanimated/use-shared-value 12)
|
||||||
|
border-radius-first-half (reanimated/use-shared-value 8)
|
||||||
|
border-radius-second-half (reanimated/use-shared-value 8)
|
||||||
|
start-x-y-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-delay translate-x-y 8 50 :linear 116.66)
|
||||||
|
(reanimated/animate-shared-value-with-delay connector-opacity 1 0 :easing1 80)
|
||||||
|
(reanimated/animate-shared-value-with-delay width 56 83.33 :easing1 63.33)
|
||||||
|
(reanimated/animate-shared-value-with-delay height 56 83.33 :easing1 63.33)
|
||||||
|
(reanimated/animate-shared-value-with-delay border-radius-first-half 28 83.33 :easing1 63.33)
|
||||||
|
(reanimated/animate-shared-value-with-delay border-radius-second-half 28 83.33 :easing1 63.33))
|
||||||
|
reset-x-y-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-x-y 0 100 :linear)
|
||||||
|
(reanimated/set-shared-value connector-opacity 0)
|
||||||
|
(reanimated/set-shared-value width 24)
|
||||||
|
(reanimated/set-shared-value height 12)
|
||||||
|
(reanimated/set-shared-value border-radius-first-half 8)
|
||||||
|
(reanimated/set-shared-value border-radius-second-half 16))
|
||||||
|
fade-in-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-x-y 0 220 :linear)
|
||||||
|
(reanimated/animate-shared-value-with-timing opacity 1 220 :linear))
|
||||||
|
fade-out-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-x-y 20 200 :linear)
|
||||||
|
(reanimated/animate-shared-value-with-timing opacity 0 200 :linear)
|
||||||
|
(reanimated/set-shared-value connector-opacity 0)
|
||||||
|
(reanimated/set-shared-value width 24)
|
||||||
|
(reanimated/set-shared-value height 12)
|
||||||
|
(reanimated/set-shared-value border-radius-first-half 8)
|
||||||
|
(reanimated/set-shared-value border-radius-second-half 16))]
|
||||||
|
(effect! #(if @recording?
|
||||||
|
(fade-in-animation)
|
||||||
|
(fade-out-animation))
|
||||||
|
[@recording?])
|
||||||
|
(effect! #(cond
|
||||||
|
@ready-to-lock?
|
||||||
|
(start-x-y-animation)
|
||||||
|
(and @recording? (not @locked?))
|
||||||
|
(reset-x-y-animation))
|
||||||
|
[@ready-to-lock?])
|
||||||
|
(effect! #(if @locked?
|
||||||
|
(fade-out-animation)
|
||||||
|
(reset-x-y-animation))
|
||||||
|
[@locked?])
|
||||||
|
[:<>
|
||||||
|
[reanimated/view {:style (style/lock-button-container opacity)}
|
||||||
|
[reanimated/view {:style (style/lock-button-connector connector-opacity width height border-radius-first-half border-radius-second-half)}]]
|
||||||
|
[reanimated/view {:style (style/lock-button translate-x-y opacity)
|
||||||
|
:pointer-events :none}
|
||||||
|
[icons/icon (if @ready-to-lock? :i/locked :i/unlocked)
|
||||||
|
{:color (colors/theme-colors colors/black colors/white)
|
||||||
|
:size 20}]]]))])
|
||||||
|
|
||||||
|
(defn- delete-button [recording? ready-to-delete?]
|
||||||
|
[:f>
|
||||||
|
(fn []
|
||||||
|
(let [opacity (reanimated/use-shared-value 0)
|
||||||
|
translate-x (reanimated/use-shared-value 20)
|
||||||
|
connector-opacity (reanimated/use-shared-value 0)
|
||||||
|
width (reanimated/use-shared-value 24)
|
||||||
|
height (reanimated/use-shared-value 12)
|
||||||
|
border-radius-first-half (reanimated/use-shared-value 8)
|
||||||
|
border-radius-second-half (reanimated/use-shared-value 8)
|
||||||
|
start-x-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-delay translate-x 12 50 :linear 133.33)
|
||||||
|
(reanimated/animate-shared-value-with-delay connector-opacity 1 0 :easing1 93.33)
|
||||||
|
(reanimated/animate-shared-value-with-delay width 56 83.33 :easing1 80)
|
||||||
|
(reanimated/animate-shared-value-with-delay height 56 83.33 :easing1 80)
|
||||||
|
(reanimated/animate-shared-value-with-delay border-radius-first-half 28 83.33 :easing1 80)
|
||||||
|
(reanimated/animate-shared-value-with-delay border-radius-second-half 28 83.33 :easing1 80))
|
||||||
|
reset-x-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-x 0 100 :linear)
|
||||||
|
(reanimated/set-shared-value connector-opacity 0)
|
||||||
|
(reanimated/set-shared-value width 24)
|
||||||
|
(reanimated/set-shared-value height 12)
|
||||||
|
(reanimated/set-shared-value border-radius-first-half 8)
|
||||||
|
(reanimated/set-shared-value border-radius-second-half 16))
|
||||||
|
fade-in-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-x 0 200 :linear)
|
||||||
|
(reanimated/animate-shared-value-with-timing opacity 1 200 :linear))
|
||||||
|
fade-out-animation (fn []
|
||||||
|
(reanimated/animate-shared-value-with-timing translate-x 20 200 :linear)
|
||||||
|
(reanimated/animate-shared-value-with-timing opacity 0 200 :linear)
|
||||||
|
(reanimated/set-shared-value connector-opacity 0)
|
||||||
|
(reanimated/set-shared-value width 24)
|
||||||
|
(reanimated/set-shared-value height 12)
|
||||||
|
(reanimated/set-shared-value border-radius-first-half 8)
|
||||||
|
(reanimated/set-shared-value border-radius-second-half 16))]
|
||||||
|
(effect! #(if @recording?
|
||||||
|
(fade-in-animation)
|
||||||
|
(fade-out-animation))
|
||||||
|
[@recording?])
|
||||||
|
(effect! #(cond
|
||||||
|
@ready-to-delete?
|
||||||
|
(start-x-animation)
|
||||||
|
@recording?
|
||||||
|
(reset-x-animation))
|
||||||
|
[@ready-to-delete?])
|
||||||
|
[:<>
|
||||||
|
[reanimated/view {:style (style/delete-button-container opacity)}
|
||||||
|
[reanimated/view {:style (style/delete-button-connector connector-opacity width height border-radius-first-half border-radius-second-half)}]]
|
||||||
|
[reanimated/view {:style (style/delete-button translate-x opacity)
|
||||||
|
:pointer-events :none}
|
||||||
|
[icons/icon :i/delete {:color colors/white
|
||||||
|
:size 20}]]]))])
|
||||||
|
|
||||||
|
(defn- record-button [recording? reviewing-audio?]
|
||||||
|
[:f>
|
||||||
|
(fn []
|
||||||
|
(let [opacity (reanimated/use-shared-value 1)
|
||||||
|
show-animation #(reanimated/set-shared-value opacity 1)
|
||||||
|
hide-animation #(reanimated/set-shared-value opacity 0)]
|
||||||
|
(effect! #(if (or @recording? @reviewing-audio?)
|
||||||
|
(hide-animation)
|
||||||
|
(show-animation))
|
||||||
|
[@recording? @reviewing-audio?])
|
||||||
|
[reanimated/view {:style (style/record-button-container opacity)}
|
||||||
|
[button/button {:type :outline
|
||||||
|
:size 32
|
||||||
|
:width 32
|
||||||
|
:accessibility-label :mic-button}
|
||||||
|
[icons/icon :i/audio {:color (colors/theme-colors colors/neutral-100 colors/white)}]]]))])
|
||||||
|
|
||||||
|
(defn input-view []
|
||||||
|
[:f>
|
||||||
|
(fn []
|
||||||
|
(let [recording? (reagent/atom false)
|
||||||
|
locked? (reagent/atom false)
|
||||||
|
ready-to-send? (reagent/atom false)
|
||||||
|
ready-to-lock? (reagent/atom false)
|
||||||
|
ready-to-delete? (reagent/atom false)
|
||||||
|
reviewing-audio? (reagent/atom false)
|
||||||
|
clear-timeout (atom nil)
|
||||||
|
record-button-at-initial-position? (atom true)
|
||||||
|
record-button-is-animating? (atom false)
|
||||||
|
touch-active? (atom false)
|
||||||
|
recording-timer (atom nil)
|
||||||
|
recording-length-ms (atom 0)
|
||||||
|
on-start-should-set-responder (fn [^js e]
|
||||||
|
(when-not @locked?
|
||||||
|
(let [pressed-record-button? (touch-inside-area?
|
||||||
|
{:location-x (oops/oget e "nativeEvent.locationX")
|
||||||
|
:location-y (oops/oget e "nativeEvent.locationY")
|
||||||
|
:ignore-min-y? false
|
||||||
|
:ignore-max-y? false
|
||||||
|
:ignore-min-x? false
|
||||||
|
:ignore-max-x? false}
|
||||||
|
record-button-area)]
|
||||||
|
(when-not @reviewing-audio?
|
||||||
|
(reset! recording? pressed-record-button?)
|
||||||
|
(when pressed-record-button?
|
||||||
|
;; TODO: By now we just track recording length, we need to add actual audio recording logic
|
||||||
|
;; GitHub issue [#14558]: https://github.com/status-im/status-mobile/issues/14558
|
||||||
|
(reset! recording-timer (utils/set-interval #(reset! recording-length-ms (+ @recording-length-ms 500)) 500))))
|
||||||
|
(reset! touch-active? true)))
|
||||||
|
true)
|
||||||
|
on-responder-move (fn [^js e]
|
||||||
|
(when-not @locked?
|
||||||
|
(let [location-x (oops/oget e "nativeEvent.locationX")
|
||||||
|
location-y (oops/oget e "nativeEvent.locationY")
|
||||||
|
page-x (oops/oget e "nativeEvent.pageX")
|
||||||
|
page-y (oops/oget e "nativeEvent.pageY")
|
||||||
|
moved-to-send-button? (touch-inside-area?
|
||||||
|
{:location-x location-x
|
||||||
|
:location-y location-y
|
||||||
|
:ignore-min-y? true
|
||||||
|
:ignore-max-y? false
|
||||||
|
:ignore-min-x? false
|
||||||
|
:ignore-max-x? true}
|
||||||
|
(send-button-area @ready-to-send?))
|
||||||
|
moved-to-delete-button? (touch-inside-area?
|
||||||
|
{:location-x location-x
|
||||||
|
:location-y location-y
|
||||||
|
:ignore-min-y? false
|
||||||
|
:ignore-max-y? true
|
||||||
|
:ignore-min-x? true
|
||||||
|
:ignore-max-x? false}
|
||||||
|
(delete-button-area @ready-to-delete?))
|
||||||
|
moved-to-lock-button? (touch-inside-area?
|
||||||
|
{:location-x location-x
|
||||||
|
:location-y location-y
|
||||||
|
:ignore-min-y? false
|
||||||
|
:ignore-max-y? false
|
||||||
|
:ignore-min-x? false
|
||||||
|
:ignore-max-x? false}
|
||||||
|
(lock-button-area @ready-to-lock?))
|
||||||
|
moved-to-record-button? (and
|
||||||
|
(touch-inside-area?
|
||||||
|
{:location-x location-x
|
||||||
|
:location-y location-y
|
||||||
|
:ignore-min-y? false
|
||||||
|
:ignore-max-y? false
|
||||||
|
:ignore-min-x? false
|
||||||
|
:ignore-max-x? false}
|
||||||
|
record-button-area-big)
|
||||||
|
(not= location-x page-x)
|
||||||
|
(not= location-y page-y))]
|
||||||
|
(cond
|
||||||
|
(and
|
||||||
|
(or
|
||||||
|
(and moved-to-record-button? @ready-to-lock?)
|
||||||
|
(and (not @locked?) moved-to-lock-button? @record-button-at-initial-position?))
|
||||||
|
(not @ready-to-delete?)
|
||||||
|
(not @ready-to-send?)
|
||||||
|
@recording?) (reset! ready-to-lock? moved-to-lock-button?)
|
||||||
|
(and
|
||||||
|
(or
|
||||||
|
(and moved-to-record-button? @ready-to-delete?)
|
||||||
|
(and moved-to-delete-button? @record-button-at-initial-position?))
|
||||||
|
(not @ready-to-lock?)
|
||||||
|
(not @ready-to-send?)
|
||||||
|
@recording?) (reset! ready-to-delete? moved-to-delete-button?)
|
||||||
|
(and
|
||||||
|
(or
|
||||||
|
(and moved-to-record-button? @ready-to-send?)
|
||||||
|
(and moved-to-send-button? @record-button-at-initial-position?))
|
||||||
|
(not @ready-to-lock?)
|
||||||
|
(not @ready-to-delete?)
|
||||||
|
@recording?) (reset! ready-to-send? moved-to-send-button?)))))
|
||||||
|
on-responder-release (fn [^js e]
|
||||||
|
(let [on-record-button? (touch-inside-area?
|
||||||
|
{:location-x (oops/oget e "nativeEvent.locationX")
|
||||||
|
:location-y (oops/oget e "nativeEvent.locationY")
|
||||||
|
:ignore-min-y? false
|
||||||
|
:ignore-max-y? false
|
||||||
|
:ignore-min-x? false
|
||||||
|
:ignore-max-x? false}
|
||||||
|
(if @reviewing-audio? record-button-area record-button-area-big))]
|
||||||
|
(cond
|
||||||
|
(and @reviewing-audio? on-record-button?)
|
||||||
|
(reset! reviewing-audio? false)
|
||||||
|
(and @ready-to-lock? (not @record-button-is-animating?))
|
||||||
|
(do
|
||||||
|
(reset! locked? true)
|
||||||
|
(reset! ready-to-lock? false))
|
||||||
|
(and (not @reviewing-audio?) on-record-button?)
|
||||||
|
(do
|
||||||
|
(when (>= @recording-length-ms 500) (reset! reviewing-audio? true))
|
||||||
|
(reset! locked? false)
|
||||||
|
(reset! recording? false)
|
||||||
|
(reset! ready-to-lock? false)
|
||||||
|
(utils/clear-interval @recording-timer)
|
||||||
|
(reset! recording-length-ms 0))
|
||||||
|
(and (not @locked?) (not @reviewing-audio?) (not @record-button-is-animating?))
|
||||||
|
(do
|
||||||
|
(reset! recording? false)
|
||||||
|
(reset! ready-to-send? false)
|
||||||
|
(reset! ready-to-delete? false)
|
||||||
|
(reset! ready-to-lock? false)
|
||||||
|
(utils/clear-interval @recording-timer)
|
||||||
|
(reset! recording-length-ms 0))))
|
||||||
|
(reset! touch-active? false))]
|
||||||
|
(fn []
|
||||||
|
[rn/view {:style style/input-container
|
||||||
|
:pointer-events :box-only
|
||||||
|
:on-start-should-set-responder on-start-should-set-responder
|
||||||
|
:on-responder-move on-responder-move
|
||||||
|
:on-responder-release on-responder-release}
|
||||||
|
[delete-button recording? ready-to-delete?]
|
||||||
|
[lock-button recording? ready-to-lock? locked?]
|
||||||
|
[send-button recording? ready-to-send? reviewing-audio?]
|
||||||
|
[record-button-big
|
||||||
|
recording?
|
||||||
|
ready-to-send?
|
||||||
|
ready-to-lock?
|
||||||
|
ready-to-delete?
|
||||||
|
record-button-is-animating?
|
||||||
|
record-button-at-initial-position?
|
||||||
|
locked?
|
||||||
|
reviewing-audio?
|
||||||
|
recording-timer
|
||||||
|
recording-length-ms
|
||||||
|
clear-timeout
|
||||||
|
touch-active?]
|
||||||
|
[record-button recording? reviewing-audio?]])))])
|
|
@ -13,6 +13,20 @@
|
||||||
(let [rgb (string/split value #",")]
|
(let [rgb (string/split value #",")]
|
||||||
(str (string/join "," (butlast rgb)) "," opacity ")")))))
|
(str (string/join "," (butlast rgb)) "," opacity ")")))))
|
||||||
|
|
||||||
|
(defn- alpha-opaque [value opacity]
|
||||||
|
(when value
|
||||||
|
(if (string/starts-with? value "#")
|
||||||
|
(let [hex (string/replace value #"#" "")
|
||||||
|
r (- 255 (* opacity (- 255 (js/parseInt (subs hex 0 2) 16))))
|
||||||
|
g (- 255 (* opacity (- 255 (js/parseInt (subs hex 2 4) 16))))
|
||||||
|
b (- 255 (* opacity (- 255 (js/parseInt (subs hex 4 6) 16))))]
|
||||||
|
(str "rgb(" r "," g "," b ")"))
|
||||||
|
(let [rgb (string/split value #",")
|
||||||
|
r (- 255 (* opacity (- 255 (get rgb 0))))
|
||||||
|
g (- 255 (* opacity (- 255 (get rgb 1))))
|
||||||
|
b (- 255 (* opacity (- 255 (get rgb 2))))]
|
||||||
|
(str "rgb(" r "," g "," b ")")))))
|
||||||
|
|
||||||
(def theme-alpha
|
(def theme-alpha
|
||||||
(memoize
|
(memoize
|
||||||
(fn
|
(fn
|
||||||
|
@ -49,6 +63,7 @@
|
||||||
;;80 with transparency
|
;;80 with transparency
|
||||||
(def neutral-80-opa-5 (alpha neutral-80 0.05))
|
(def neutral-80-opa-5 (alpha neutral-80 0.05))
|
||||||
(def neutral-80-opa-10 (alpha neutral-80 0.1))
|
(def neutral-80-opa-10 (alpha neutral-80 0.1))
|
||||||
|
(def neutral-80-opa-15 (alpha neutral-80 0.15))
|
||||||
(def neutral-80-opa-20 (alpha neutral-80 0.2))
|
(def neutral-80-opa-20 (alpha neutral-80 0.2))
|
||||||
(def neutral-80-opa-30 (alpha neutral-80 0.3))
|
(def neutral-80-opa-30 (alpha neutral-80 0.3))
|
||||||
(def neutral-80-opa-40 (alpha neutral-80 0.4))
|
(def neutral-80-opa-40 (alpha neutral-80 0.4))
|
||||||
|
@ -75,6 +90,9 @@
|
||||||
(def neutral-100-opa-95 (alpha neutral-100 0.95))
|
(def neutral-100-opa-95 (alpha neutral-100 0.95))
|
||||||
(def neutral-100-opa-100 (alpha neutral-100 1))
|
(def neutral-100-opa-100 (alpha neutral-100 1))
|
||||||
|
|
||||||
|
;;80 with transparency opaque
|
||||||
|
(def neutral-80-opa-5-opaque (alpha-opaque neutral-80 0.05))
|
||||||
|
|
||||||
;;;;White
|
;;;;White
|
||||||
|
|
||||||
;;Solid
|
;;Solid
|
||||||
|
@ -93,6 +111,11 @@
|
||||||
(def white-opa-90 (alpha white 0.9))
|
(def white-opa-90 (alpha white 0.9))
|
||||||
(def white-opa-95 (alpha white 0.95))
|
(def white-opa-95 (alpha white 0.95))
|
||||||
|
|
||||||
|
;;;;Black
|
||||||
|
|
||||||
|
;;Solid
|
||||||
|
(def black "#000000")
|
||||||
|
|
||||||
;;;;Primary
|
;;;;Primary
|
||||||
|
|
||||||
;;Solid
|
;;Solid
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
[clojure.string :as string]
|
[clojure.string :as string]
|
||||||
["react-native-linear-gradient" :default LinearGradient]
|
["react-native-linear-gradient" :default LinearGradient]
|
||||||
["react-native-reanimated" :default reanimated
|
["react-native-reanimated" :default reanimated
|
||||||
:refer (useSharedValue useAnimatedStyle withTiming withDelay withSpring withRepeat Easing Keyframe)]))
|
:refer (useSharedValue useAnimatedStyle withTiming withDelay withSpring withRepeat Easing Keyframe cancelAnimation)]))
|
||||||
|
|
||||||
;; Animated Components
|
;; Animated Components
|
||||||
(def create-animated-component (comp reagent/adapt-react-class (.-createAnimatedComponent reanimated)))
|
(def create-animated-component (comp reagent/adapt-react-class (.-createAnimatedComponent reanimated)))
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
(def with-spring withSpring)
|
(def with-spring withSpring)
|
||||||
(def key-frame Keyframe)
|
(def key-frame Keyframe)
|
||||||
(def with-repeat withRepeat)
|
(def with-repeat withRepeat)
|
||||||
|
(def cancel-animation cancelAnimation)
|
||||||
|
|
||||||
;; Easings
|
;; Easings
|
||||||
(def bezier (.-bezier ^js Easing))
|
(def bezier (.-bezier ^js Easing))
|
||||||
|
@ -54,6 +55,12 @@
|
||||||
;; Worklets
|
;; Worklets
|
||||||
(def worklet-factory (js/require "../src/js/worklet_factory.js"))
|
(def worklet-factory (js/require "../src/js/worklet_factory.js"))
|
||||||
|
|
||||||
|
(defn interpolate [shared-value input-range output-range]
|
||||||
|
(.interpolateValue ^js worklet-factory
|
||||||
|
shared-value
|
||||||
|
(clj->js input-range)
|
||||||
|
(clj->js output-range)))
|
||||||
|
|
||||||
;;;; Component Animations
|
;;;; Component Animations
|
||||||
|
|
||||||
;; kebab-case styles are not working for worklets
|
;; kebab-case styles are not working for worklets
|
||||||
|
@ -75,4 +82,16 @@
|
||||||
|
|
||||||
(defn animate-shared-value-with-repeat [anim val duration easing number-of-repetitions reverse?]
|
(defn animate-shared-value-with-repeat [anim val duration easing number-of-repetitions reverse?]
|
||||||
(set-shared-value anim (with-repeat (with-timing val (js-obj "duration" duration
|
(set-shared-value anim (with-repeat (with-timing val (js-obj "duration" duration
|
||||||
"easing" (get easings easing))) number-of-repetitions reverse?)))
|
"easing" (get easings easing))) number-of-repetitions reverse?)))
|
||||||
|
|
||||||
|
(defn animate-shared-value-with-delay-repeat
|
||||||
|
([anim val duration easing delay number-of-repetitions]
|
||||||
|
(animate-shared-value-with-delay-repeat anim val duration easing delay number-of-repetitions false))
|
||||||
|
([anim val duration easing delay number-of-repetitions reverse?]
|
||||||
|
(set-shared-value anim
|
||||||
|
(with-delay delay
|
||||||
|
(with-repeat
|
||||||
|
(with-timing val
|
||||||
|
#js {:duration duration
|
||||||
|
:easing (get easings easing)})
|
||||||
|
number-of-repetitions reverse?)))))
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
[status-im2.contexts.quo-preview.notifications.activity-logs :as activity-logs]
|
[status-im2.contexts.quo-preview.notifications.activity-logs :as activity-logs]
|
||||||
[status-im2.contexts.quo-preview.posts-and-attachments.messages-skeleton :as messages-skeleton]
|
[status-im2.contexts.quo-preview.posts-and-attachments.messages-skeleton :as messages-skeleton]
|
||||||
[status-im2.contexts.quo-preview.reactions.react :as react]
|
[status-im2.contexts.quo-preview.reactions.react :as react]
|
||||||
|
[status-im2.contexts.quo-preview.record-audio.record-audio :as record-audio]
|
||||||
[status-im2.contexts.quo-preview.selectors.disclaimer :as disclaimer]
|
[status-im2.contexts.quo-preview.selectors.disclaimer :as disclaimer]
|
||||||
[status-im2.contexts.quo-preview.selectors.selectors :as selectors]
|
[status-im2.contexts.quo-preview.selectors.selectors :as selectors]
|
||||||
[status-im2.contexts.quo-preview.settings.privacy-option :as privacy-option]
|
[status-im2.contexts.quo-preview.settings.privacy-option :as privacy-option]
|
||||||
|
@ -164,6 +165,9 @@
|
||||||
:reactions [{:name :react
|
:reactions [{:name :react
|
||||||
:insets {:top false}
|
:insets {:top false}
|
||||||
:component react/preview-react}]
|
:component react/preview-react}]
|
||||||
|
:record-audio [{:name :record-audio
|
||||||
|
:insets {:top false}
|
||||||
|
:component record-audio/preview-record-audio}]
|
||||||
:switcher [{:name :switcher-cards
|
:switcher [{:name :switcher-cards
|
||||||
:insets {:top false}
|
:insets {:top false}
|
||||||
:component switcher-cards/preview-switcher-cards}]
|
:component switcher-cards/preview-switcher-cards}]
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
(ns status-im2.contexts.quo-preview.record-audio.record-audio
|
||||||
|
(:require [react-native.core :as rn]
|
||||||
|
[quo2.components.record-audio.record-audio.view :as record-audio]))
|
||||||
|
|
||||||
|
(defn cool-preview []
|
||||||
|
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
|
||||||
|
[rn/view
|
||||||
|
[rn/view {:padding-top 150
|
||||||
|
:align-items :center
|
||||||
|
:background-color :transparent}
|
||||||
|
[record-audio/input-view]]]])
|
||||||
|
|
||||||
|
(defn preview-record-audio []
|
||||||
|
[rn/view {:flex 1}
|
||||||
|
[rn/flat-list {:flex 1
|
||||||
|
:keyboard-should-persist-taps :never
|
||||||
|
:scroll-enabled false
|
||||||
|
:header [cool-preview]
|
||||||
|
:key-fn str}]])
|
Loading…
Reference in New Issue