Compare commits

...
Author SHA1 Message Date
Ulises M b778f62e6d Nashorn attempt 2024-03-13 16:49:58 -06:00
Ulises M ac6e3cdb2c Reimplement avatar animations using new worklet approach 2024-03-13 13:44:32 -06:00
Ulises M 691c6b67ce Add worklet translation to shadow-cljs 2024-03-13 13:42:12 -06:00
10 changed files with 4890 additions and 2596 deletions
+6 -3
View File
@@ -1,6 +1,9 @@
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: ['react-native-reanimated/plugin', '@babel/plugin-transform-named-capturing-groups-regex'],
presets: [
"@babel/preset-env"
// 'module:metro-react-native-babel-preset'
],
/*plugins: ['react-native-reanimated/plugin', '@babel/plugin-transform-named-capturing-groups-regex'],
env: {
test: {
presets: [
@@ -15,5 +18,5 @@ module.exports = {
],
],
},
},
},*/
};
+1
View File
@@ -78,6 +78,7 @@
"@babel/helper-builder-react-jsx": "^7.20.0",
"@babel/plugin-transform-block-scoping": "^7.20.0",
"@babel/preset-env": "^7.20.0",
"@babel/preset-es2015": "^7.0.0-beta.53",
"@babel/preset-react": "^7.18.6",
"@babel/register": "7.0.0",
"@jest/globals": "^25.1.0",
+1
View File
@@ -46,6 +46,7 @@
;; To match the folder created by Nix build of JSBundle.
:output-dir "result"
:init-fn status-im.core/init
:build-hooks [(status-im.setup.build-hooks.worklets/transform-output)]
;; When false, the Shadow-CLJS watcher won't automatically refresh
;; the target files (a.k.a hot reload). When false, you can manually
;; reload by calling `shadow.cljs.devtools.api/watch-compile-all!`.
+4 -1
View File
@@ -20,7 +20,8 @@
LinearTransition
enableLayoutAnimations
useAnimatedScrollHandler
runOnJS)]
runOnJS)
:as reanimated*]
["react-native-redash" :refer (withPause)]
[react-native.flat-list :as rn-flat-list]
[react-native.utils :as rn.utils]
@@ -107,6 +108,8 @@
(when (and anim (some? v))
(set! (.-value anim) v)))
(def interpolate* reanimated*/interpolate)
(defn interpolate
([shared-value input-range output-range]
(interpolate shared-value input-range output-range nil))
+57 -24
View File
@@ -1,31 +1,36 @@
(ns status-im.common.scalable-avatar.view
(ns ^:workletize status-im.common.scalable-avatar.view
(:require [quo.core :as quo]
[react-native.reanimated :as reanimated]
[status-im.common.scalable-avatar.style :as style]))
(def scroll-animation-input-range [0 50])
(def header-extrapolation-option
{:extrapolateLeft "clamp"
:extrapolateRight "clamp"})
;;[status-im.common.scalable-avatar.style :as style]
[status-im.contexts.profile.settings.header.style :as style]))
(defn f-avatar
[{:keys [scroll-y full-name online? profile-picture customization-color border-color]}]
(let [image-scale-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[1 0.4]
header-extrapolation-option)
image-top-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 20]
header-extrapolation-option)
image-side-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[-4 -20]
header-extrapolation-option)]
[reanimated/view
{:style (style/wrapper {:scale image-scale-animation
:margin-top image-top-margin-animation
:margin image-side-margin-animation
:border-color border-color})}
[{:keys [scroll-y full-name online? profile-picture customization-color]}]
(let [avatar-total-size 88
border-height 4
translation-to-bottom (fn [scale inverse-scale]
(js* "'worklet'")
(let [current-avatar-size (* avatar-total-size (- 1 scale))
current-center (/ current-avatar-size 2)]
(* current-center inverse-scale)))
transform (reanimated/use-animated-style
(fn []
(js* "'worklet'")
(let [scale (reanimated/interpolate*
(.-value scroll-y)
#js [0 48]
#js [1 0.4]
"clamp")
inverse-scale (/ 1 scale)
translation (translation-to-bottom scale inverse-scale)
bottom (* border-height inverse-scale (- 1 scale))]
#js
{:transform #js
[#js {:scale scale}
#js {:translateX (- translation)}
#js {:translateY (- translation bottom)}]})))
theme (quo.theme/get-theme)]
[reanimated/view {:style [transform (style/avatar-container theme)]}
[quo/user-avatar
{:full-name full-name
:online? online?
@@ -35,6 +40,34 @@
:customization-color customization-color
:size :big}]]))
#_(defn f-avatar
[{:keys [scroll-y full-name online? profile-picture customization-color border-color]}]
(let [image-scale-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[1 0.4]
header-extrapolation-option)
image-top-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 20]
header-extrapolation-option)
image-side-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[-4 -20]
header-extrapolation-option)]
[reanimated/view
{:style (style/wrapper {:scale image-scale-animation
:margin-top image-top-margin-animation
:margin image-side-margin-animation
:border-color border-color})}
[quo/user-avatar
{:full-name full-name
:online? online?
:profile-picture profile-picture
:status-indicator? true
:ring? true
:customization-color customization-color
:size :big}]]))
(defn view
[props]
[:f> f-avatar props])
@@ -1,4 +1,4 @@
(ns status-im.contexts.profile.settings.header.header-shape
(ns ^:workletize status-im.contexts.profile.settings.header.header-shape
(:require [quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
@@ -21,13 +21,17 @@
(defn f-view
[{:keys [scroll-y customization-color theme]}]
(let [background-color (colors/resolve-color customization-color theme 40)
opacity-animation (reanimated/interpolate scroll-y
[0 45 50]
[1 1 0])]
(let [background-color (colors/resolve-color customization-color theme 40)
opacity (reanimated/use-animated-style
(fn []
(js* "'worklet'")
#js
{:opacity (reanimated/interpolate* (.-value scroll-y)
#js [0 45 50]
#js [1 1 0])}))]
[:<>
[rn/view {:style (style/header-middle-shape background-color)}]
[reanimated/view {:style (style/radius-container opacity-animation)}
[reanimated/view {:style [opacity style/radius-container]}
[left-radius background-color]
[right-radius background-color]]]))
@@ -27,19 +27,13 @@
:height 48
:flex-grow 1})
(defn radius-container
[opacity-animation]
{:opacity opacity-animation
:flex-direction :row
(def radius-container
{:flex-direction :row
:justify-content :space-between})
(defn avatar-container
[theme scale-animation top-margin-animation side-margin-animation]
[{:transform [{:scale scale-animation}]
:margin-top top-margin-animation
:margin-left side-margin-animation
:margin-bottom side-margin-animation}
{:align-items :flex-start
:border-width 4
:border-color (colors/theme-colors colors/border-avatar-light colors/neutral-80-opa-80 theme)
:border-radius 100}])
[theme]
{:align-items :flex-start
:border-width 4
:border-color (colors/theme-colors colors/border-avatar-light colors/neutral-80-opa-80 theme)
:border-radius 44})
@@ -0,0 +1,74 @@
(ns status-im.setup.build-hooks.worklets
(:require [clojure.set]
[clojure.java.io :as io]
[cljs.build.api :as b])
(:import (java.io BufferedReader InputStreamReader PrintWriter)
(javax.script ScriptEngineManager)))
(def engine
(doto (.getEngineByName (ScriptEngineManager.) "nashorn")
(.eval (io/reader (io/file "babel.min.js")))))
(defn- update-js-output
[build-state code-processed]
(reduce-kv (fn [prev-build-state ns-key new-code]
(assoc-in prev-build-state [:output ns-key :js] new-code))
build-state
code-processed))
(defn- gen-workletized-code!
[code-seq store-atom]
(doall
(pmap (fn [[[_ filepath :as ns-key] js-code]]
(println "Workletizing:" filepath) ;; TODO: debug remove
(def js-code* js-code)
(try
(let [command "node workletize-code.js"
process (.exec (Runtime/getRuntime) command)
output-stream (.getOutputStream process)
writer (PrintWriter. output-stream)
reader (BufferedReader. (InputStreamReader. (.getInputStream process)))]
(.println writer js-code)
(.flush writer)
(.close writer)
(let [output (apply str (interleave (line-seq reader) (repeat "\n")))
_exit-code (.waitFor process)]
(swap! store-atom assoc ns-key output)))
(catch Exception e
(println (str "Exception while workletizing: " filepath "\n")
(.getMessage e)))))
code-seq)))
(defn- get-js-code-with-ns
[build-state-output file-path]
(let [ns-key [:shadow.build.classpath/resource file-path]
js-code (get-in build-state-output [ns-key :js])]
[ns-key js-code]))
(defn- get-files-to-workletize
[{:keys [shadow.build/build-info compiler-env] :as _build-state}]
(let [files-compiled (->> build-info
:compiled
(map second)
(set))
namespaces-metadata (->> compiler-env
:cljs.analyzer/namespaces
vals
(map :meta))
files-marked (->> namespaces-metadata
(filter :workletize)
(map :file)
(set))]
(clojure.set/intersection files-compiled files-marked)))
(defn transform-output
{:shadow.build/stage :compile-finish}
[{:keys [output] :as build-state}]
(let [files-to-workletize (get-files-to-workletize build-state)
js-code-with-ns (map #(get-js-code-with-ns output %) files-to-workletize)
code-processed-store (atom {})]
(gen-workletized-code! js-code-with-ns code-processed-store)
(update-js-output build-state @code-processed-store)))
File diff suppressed because one or more lines are too long
+4702 -2549
View File
File diff suppressed because it is too large Load Diff