feat: lint direct require quo component outside src/quo (#17828)

This commit is contained in:
yqrashawn 2023-11-07 10:21:58 +08:00 committed by GitHub
parent b47c97a4fd
commit 701df811b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 65 additions and 53 deletions

View File

@ -7,3 +7,4 @@ modules
result result
target target
component-spec component-spec
/app

View File

@ -312,6 +312,7 @@ lint: export TARGET := clojure
lint: export CLJ_LINTER_PRINT_WARNINGS ?= false lint: export CLJ_LINTER_PRINT_WARNINGS ?= false
lint: ##@test Run code style checks lint: ##@test Run code style checks
@sh scripts/lint-re-frame-in-quo-components.sh && \ @sh scripts/lint-re-frame-in-quo-components.sh && \
sh scripts/lint-direct-require-component-outside-quo.sh && \
clj-kondo --config .clj-kondo/config.edn --cache false --fail-level error --lint src $(if $(filter $(CLJ_LINTER_PRINT_WARNINGS),true),,| grep -v ': warning: ') && \ clj-kondo --config .clj-kondo/config.edn --cache false --fail-level error --lint src $(if $(filter $(CLJ_LINTER_PRINT_WARNINGS),true),,| grep -v ': warning: ') && \
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \ ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \ zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \

View File

@ -23,7 +23,7 @@ setups and runs the test suite once.
setups and runs the test suite and watches for code changes will then retrigger the test suite. setups and runs the test suite and watches for code changes will then retrigger the test suite.
## Writing Tests ## Writing Tests
New test files will need their namespace added to either the file "src/quo2/core_spec.cljs" or "src/status_im2/core_spec.cljs. These locations may update overtime but it is dependent on the entrypoint in shadow-cljs config discussed below. New test files will need their namespace added to either the file "src/quo/core_spec.cljs" or "src/status_im2/core_spec.cljs. These locations may update overtime but it is dependent on the entrypoint in shadow-cljs config discussed below.
### Best practices ### Best practices

View File

@ -76,7 +76,7 @@ It's important to name functional components with `f-` prefix.
### Component props and API scheme to match Figma as closely as possible ### Component props and API scheme to match Figma as closely as possible
Ideally, the prop names for components (particularly in quo2 Design System) Ideally, the prop names for components (particularly in quo Design System)
should match the Figma properties as best as possible. This makes it easier for should match the Figma properties as best as possible. This makes it easier for
the developer using that component to configure it correctly for the screen it the developer using that component to configure it correctly for the screen it
is being used on and avoids unnecessary overwrites and adjustments being made. is being used on and avoids unnecessary overwrites and adjustments being made.
@ -134,7 +134,7 @@ For example if Figma has sizes `:small`, `:medium` and `:large`
Prefer to define styles in a separate file named `style.cljs`, colocated with Prefer to define styles in a separate file named `style.cljs`, colocated with
the source file. For a real example, see the source file. For a real example, see
[src/quo2/components/record_audio/record_audio/style.cljs](../src/quo2/components/record_audio/record_audio/style.cljs). [src/quo/components/record_audio/record_audio/style.cljs](../src/quo/components/record_audio/record_audio/style.cljs).
```clojure ```clojure
;; bad ;; bad
@ -528,27 +528,27 @@ due to performance constraints.
(:preferred-name multiaccount))) (:preferred-name multiaccount)))
``` ```
### Requiring quo2 components ### Requiring quo components
Consume `quo2` components from `quo2.core`, unless the namespace is also inside Consume `quo` components from `quo.core`, unless the namespace is also inside
the `quo2/` directory. the `quo/` directory.
```clojure ```clojure
;; bad ;; bad
(ns my-namespace (ns my-namespace
(:require [quo2.components.icon :as icon])) (:require [quo.components.icon :as icon]))
(icon/icon :i/verified) (icon/icon :i/verified)
;; good ;; good
(ns my-namespace (ns my-namespace
(:require [quo2.core :as quo])) (:require [quo.core :as quo]))
(quo/icon :i/verified) (quo/icon :i/verified)
;; also good because both namespaces are inside quo2/ ;; also good because both namespaces are inside quo/
(ns quo2.components.tabs.account-selector (ns quo.components.tabs.account-selector
(:require [quo2.components.markdown.text :as text])) (:require [quo.components.markdown.text :as text]))
``` ```
### Require/import ### Require/import
@ -615,12 +615,12 @@ Use the appropriate keyword qualification/namespace.
```clojure ```clojure
;; bad ;; bad
(require '[quo2.components.icon :as icons]) (require '[quo.components.icon :as icons])
(icons/icon :main-icons2/verified) (icons/icon :main-icons2/verified)
;; good ;; good
(require '[quo2.core :as quo2]) (require '[quo.core :as quo])
(quo2/icon :i/verified) (quo/icon :i/verified)
``` ```
### Translations ### Translations
@ -695,7 +695,7 @@ First, the bird's-eye view with some example ClojureScript files:
src src
├── js/ ├── js/
├── mocks/ ├── mocks/
├── quo2 ├── quo
│ ├── components/ │ ├── components/
│ ├── foundations/ │ ├── foundations/
│ └── theme.cljs │ └── theme.cljs
@ -716,7 +716,7 @@ src
- `src/js`: Raw Javascript files, e.g. React Native Reanimated worklets. - `src/js`: Raw Javascript files, e.g. React Native Reanimated worklets.
- `src/mocks`: Plumbing configuration to be able to run tests. - `src/mocks`: Plumbing configuration to be able to run tests.
- `src/quo2/`: The component library for Status Mobile. - `src/quo/`: The component library for Status Mobile.
- `src/react_native/`: Contains only low-level constructs to help React Native - `src/react_native/`: Contains only low-level constructs to help React Native
work in tandem with Clojure(Script). work in tandem with Clojure(Script).
- `src/status_im2/`: Directory where we try to be as strict as possible about - `src/status_im2/`: Directory where we try to be as strict as possible about
@ -728,7 +728,7 @@ src
of the directory tree. Just like directories named `utils`, their directory of the directory tree. Just like directories named `utils`, their directory
nesting level communicates their applicable limits. nesting level communicates their applicable limits.
- `src/status_im2/common/components/`: Contains reusable components that are not - `src/status_im2/common/components/`: Contains reusable components that are not
part of the design system (quo2). part of the design system (quo).
- `src/status_im2/contexts/`: Contains [bounded contexts](#glossary), like - `src/status_im2/contexts/`: Contains [bounded contexts](#glossary), like
`browser/`, `messaging/`, etc. As much as possible, _bounded contexts_ should `browser/`, `messaging/`, etc. As much as possible, _bounded contexts_ should
not directly require each other's namespaces. not directly require each other's namespaces.
@ -743,9 +743,9 @@ directory nesting level precisely indicates its boundaries. For example, a
`contexts/user_settings/utils/datetime.cljs` file communicates that it should `contexts/user_settings/utils/datetime.cljs` file communicates that it should
only be used in the `user_settings` context. only be used in the `user_settings` context.
### src/quo2 ### src/quo
The `src/quo2/` directory holds all components for the new design system. As The `src/quo/` directory holds all components for the new design system. As
much as possible, its sub-directories and component names should reflect the much as possible, its sub-directories and component names should reflect the
same language used by designers. same language used by designers.
@ -753,14 +753,14 @@ Even though the directory lives alongside the rest of the codebase, we should
think of it as an external entity that abstracts away particular Status domain think of it as an external entity that abstracts away particular Status domain
knowledge. knowledge.
Components inside `src/quo2/` should not rely on re-frame, i.e. they should not Components inside `src/quo/` should not rely on re-frame, i.e. they should not
dispatch events or use subscriptions. dispatch events or use subscriptions.
Example structure: Example structure:
``` ```
src src
└── quo2 └── quo
├── components ├── components
│ └── dropdown │ └── dropdown
│ ├── style.cljs │ ├── style.cljs

View File

@ -21,7 +21,7 @@ let
buildInputs = with pkgs; [ buildInputs = with pkgs; [
clojure flock maven openjdk clojure flock maven openjdk
# lint specific utilities # lint specific utilities
clj-kondo zprint clojure-lsp clj-kondo zprint clojure-lsp ripgrep
]; ];
# CLASSPATH from clojure deps with 'src' appended to find local sources. # CLASSPATH from clojure deps with 'src' appended to find local sources.
shellHook = with pkgs; '' shellHook = with pkgs; ''

View File

@ -0,0 +1,14 @@
#!/usr/bin/env sh
# quo components namespace ends with style|utils|types|reaction-resource
# are not the component view, they are usually utils fns or styles
if rg --pcre2 --glob '!src/quo/**/*' 'quo\.components(\.[\w-]+)*\.[\w-]*(?<!style|utils|types|reaction-resource)(\s|\]|\n)' src; then
echo "Found above direct require of quo component outside src/quo/"
echo "For more info, check the style guide https://github.com/status-im/status-mobile/blob/develop/doc/new-guidelines.md#requiring-quo-components"
exit 1
elif [ $? -eq 1 ]; then
exit 0
else
exit $?
fi

View File

@ -2,7 +2,7 @@
(:require (:require
[oops.core :as oops] [oops.core :as oops]
[quo.components.animated-header-flatlist.style :as style] [quo.components.animated-header-flatlist.style :as style]
[quo.core :as quo] [quo.components.icon :as icon]
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]
@ -73,11 +73,11 @@
{:active-opacity 1 {:active-opacity 1
:on-press back-button-on-press :on-press back-button-on-press
:style (style/button-container {:left 20 :theme theme})} :style (style/button-container {:left 20 :theme theme})}
[quo/icon :i/arrow-left {:size 20 :color (colors/theme-colors colors/black colors/white theme)}]] [icon/icon :i/arrow-left {:size 20 :color (colors/theme-colors colors/black colors/white theme)}]]
[rn/touchable-opacity [rn/touchable-opacity
{:active-opacity 1 {:active-opacity 1
:style (style/button-container {:right 20 :theme theme})} :style (style/button-container {:right 20 :theme theme})}
[quo/icon :i/options {:size 20 :color (colors/theme-colors colors/black colors/white theme)}]] [icon/icon :i/options {:size 20 :color (colors/theme-colors colors/black colors/white theme)}]]
[reanimated/blur-view [reanimated/blur-view
{:blurAmount 32 {:blurAmount 32
:blurType :light :blurType :light

View File

@ -1,6 +1,7 @@
(ns quo.core (ns quo.core
(:refer-clojure :exclude [filter]) (:refer-clojure :exclude [filter])
(:require (:require
quo.components.animated-header-flatlist.view
quo.components.avatars.account-avatar.view quo.components.avatars.account-avatar.view
quo.components.avatars.channel-avatar.view quo.components.avatars.channel-avatar.view
quo.components.avatars.collection-avatar.view quo.components.avatars.collection-avatar.view
@ -239,6 +240,7 @@
;;;; Header ;;;; Header
(def header quo.components.header/header) (def header quo.components.header/header)
(def animated-header-list quo.components.animated-header-flatlist.view/animated-header-list)
;;;; Gradient ;;;; Gradient
(def gradient-cover quo.components.gradient.gradient-cover.view/view) (def gradient-cover quo.components.gradient.gradient-cover.view/view)

View File

@ -1,14 +1,14 @@
(ns status-im.ui.screens.home.views.inner-item (ns status-im.ui.screens.home.views.inner-item
(:require (:require
[clojure.string :as string] [clojure.string :as string]
[quo.components.markdown.text :as quo.text] [quo.core :as quo]
[quo.foundations.colors :as quo.colors] [quo.foundations.colors :as quo.colors]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.ui.components.badge :as badge] [status-im.ui.components.badge :as badge]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen] [status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.ui.components.chat-icon.styles :as chat-icon.styles] [status-im.ui.components.chat-icon.styles :as chat-icon.styles]
[status-im.ui.components.colors :as colors] [status-im.ui.components.colors :as colors]
[status-im.ui.components.core :as quo] [status-im.ui.components.core :as components]
[status-im.ui.components.icons.icons :as icons] [status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.screens.home.styles :as styles] [status-im.ui.screens.home.styles :as styles]
@ -187,7 +187,7 @@
(defn chat-item-title (defn chat-item-title
[chat-id muted group-chat chat-name edit?] [chat-id muted group-chat chat-name edit?]
[quo.text/text [quo/text
{:weight :semi-bold {:weight :semi-bold
:color (when muted :secondary) :color (when muted :secondary)
:accessibility-label :chat-name-text :accessibility-label :chat-name-text
@ -206,7 +206,7 @@
(defn chat-item-title-old (defn chat-item-title-old
[chat-id muted group-chat chat-name edit?] [chat-id muted group-chat chat-name edit?]
[quo/text [components/text
{:weight :medium {:weight :medium
:color (when muted :secondary) :color (when muted :secondary)
:accessibility-label :chat-name-text :accessibility-label :chat-name-text
@ -260,7 +260,7 @@
[unviewed-indicator home-item]]) [unviewed-indicator home-item]])
[react/view {:position :absolute :left 72 :top 32 :right 80} [react/view {:position :absolute :left 72 :top 32 :right 80}
(if public? (if public?
[quo.text/text [quo/text
{:color :secondary {:color :secondary
:number-of-lines 1 :number-of-lines 1
:ellipsize-mode :middle :ellipsize-mode :middle
@ -281,11 +281,11 @@
:container-style {:width 16 :container-style {:width 16
:height 16 :height 16
:margin-right 4}}] :margin-right 4}}]
[quo.text/text [quo/text
{:weight :medium {:weight :medium
:style {:color (quo.colors/theme-colors quo.colors/neutral-50 quo.colors/neutral-40)}} :style {:color (quo.colors/theme-colors quo.colors/neutral-50 quo.colors/neutral-40)}}
(i18n/label :t/members-count {:count (count group-members-public-keys)})]] (i18n/label :t/members-count {:count (count group-members-public-keys)})]]
[quo.text/text [quo/text
{:monospace true {:monospace true
:weight :medium :weight :medium
:style {:color (quo.colors/theme-colors quo.colors/neutral-50 :style {:color (quo.colors/theme-colors quo.colors/neutral-50

View File

@ -1,6 +1,5 @@
(ns status-im.ui.screens.wallet.account.views (ns status-im.ui.screens.wallet.account.views
(:require (:require
[quo.components.markdown.text :as quo.text]
[quo.core :as quo] [quo.core :as quo]
[quo.foundations.colors :as quo.colors] [quo.foundations.colors :as quo.colors]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
@ -288,7 +287,7 @@
:shadow-color (:shadow-01 @colors/theme) :shadow-color (:shadow-01 @colors/theme)
:shadow-offset {:width 0 :height 4}} :shadow-offset {:width 0 :height 4}}
[react/view {:padding 20} [react/view {:padding 20}
[quo.text/text {:size :heading-2 :weight :semi-bold} (str portfolio-value " " (:code currency))]] [quo/text {:size :heading-2 :weight :semi-bold} (str portfolio-value " " (:code currency))]]
[react/view [react/view
[react/scroll-view {:horizontal true :margin-bottom 32 :showsHorizontalScrollIndicator false} [react/scroll-view {:horizontal true :margin-bottom 32 :showsHorizontalScrollIndicator false}
[react/view {:width 20}] [react/view {:width 20}]

View File

@ -1,12 +1,12 @@
(ns status-im.ui.screens.wallet.accounts.common (ns status-im.ui.screens.wallet.accounts.common
(:require (:require
[quo.components.markdown.text :as quo.text] [quo.core :as quo]
[quo.foundations.colors :as quo.colors] [quo.foundations.colors :as quo.colors]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[react-native.core :as rn] [react-native.core :as rn]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im.ui.components.chat-icon.screen :as chat-icon] [status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.core :as quo] [status-im.ui.components.core :as components]
[status-im.ui.components.list.item :as list.item] [status-im.ui.components.list.item :as list.item]
[status-im.ui.screens.wallet.components.views :as wallet.components] [status-im.ui.screens.wallet.components.views :as wallet.components]
[status-im.utils.utils :as utils.utils] [status-im.utils.utils :as utils.utils]
@ -41,13 +41,13 @@
(defn render-asset (defn render-asset
[{:keys [icon decimals amount color value] :as token} _ _ currency] [{:keys [icon decimals amount color value] :as token} _ _ currency]
[list.item/list-item [list.item/list-item
{:title [quo/text {:weight :medium} {:title [components/text {:weight :medium}
[quo/text {:weight :inherit} [components/text {:weight :inherit}
(str (if amount (str (if amount
(wallet.utils/format-amount amount decimals) (wallet.utils/format-amount amount decimals)
"...") "...")
" ")] " ")]
[quo/text [components/text
{:color :secondary {:color :secondary
:weight :inherit} :weight :inherit}
(wallet.utils/display-symbol token)]] (wallet.utils/display-symbol token)]]
@ -66,11 +66,11 @@
[chat-icon/custom-icon-view-list (:name token) color])] [chat-icon/custom-icon-view-list (:name token) color])]
[rn/view {:position :absolute :left 52 :top 8 :right 12} [rn/view {:position :absolute :left 52 :top 8 :right 12}
[rn/view {:flex-direction :row :justify-content :space-between :align-items :center} [rn/view {:flex-direction :row :justify-content :space-between :align-items :center}
[quo.text/text {:weight :semi-bold :style {:height 22}} [quo/text {:weight :semi-bold :style {:height 22}}
name] name]
[quo.text/text {:size :paragraph-2 :weight :medium} [quo/text {:size :paragraph-2 :weight :medium}
(str (if value value "...") " " currency)]] (str (if value value "...") " " currency)]]
[quo.text/text [quo/text
{:size :paragraph-2 {:size :paragraph-2
:weight :medium :weight :medium
:style {:color (quo.colors/theme-colors quo.colors/neutral-50 quo.colors/neutral-40)}} :style {:color (quo.colors/theme-colors quo.colors/neutral-50 quo.colors/neutral-40)}}

View File

@ -1,6 +1,5 @@
(ns status-im.ui.screens.wallet.accounts.views (ns status-im.ui.screens.wallet.accounts.views
(:require (:require
[quo.components.markdown.text :as quo.text]
[quo.core :as quo] [quo.core :as quo]
[quo.foundations.colors :as quo.colors] [quo.foundations.colors :as quo.colors]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
@ -207,8 +206,8 @@
(views/letsubs [currency [:wallet-legacy/currency] (views/letsubs [currency [:wallet-legacy/currency]
portfolio-value [:portfolio-value]] portfolio-value [:portfolio-value]]
[react/view {:padding-vertical 12} [react/view {:padding-vertical 12}
[quo.text/text (i18n/label :t/wallet-total-value)] [quo/text (i18n/label :t/wallet-total-value)]
[quo.text/text {:size :heading-1 :weight :semi-bold} [quo/text {:size :heading-1 :weight :semi-bold}
(str portfolio-value " " (:code currency))] (str portfolio-value " " (:code currency))]
[react/scroll-view {:horizontal true}]])) [react/scroll-view {:horizontal true}]]))

View File

@ -1,7 +1,6 @@
(ns status-im2.contexts.chat.home.chat-list-item.view (ns status-im2.contexts.chat.home.chat-list-item.view
(:require (:require
[clojure.string :as string] [clojure.string :as string]
[quo.components.icon :as icons]
[quo.core :as quo] [quo.core :as quo]
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[react-native.core :as rn] [react-native.core :as rn]
@ -193,7 +192,7 @@
[rn/view {:style style/notification-container} [rn/view {:style style/notification-container}
(cond (cond
muted muted
[icons/icon :i/muted {:color colors/neutral-40}] [quo/icon :i/muted {:color colors/neutral-40}]
(and group-chat unread-mentions?) (and group-chat unread-mentions?)
[quo/counter [quo/counter

View File

@ -1,6 +1,5 @@
(ns status-im2.contexts.chat.messages.contact-requests.bottom-drawer (ns status-im2.contexts.chat.messages.contact-requests.bottom-drawer
(:require (:require
[quo.components.drawers.permission-context.view :as permission-context]
[quo.core :as quo] [quo.core :as quo]
[react-native.core :as rn] [react-native.core :as rn]
[status-im2.config :as config] [status-im2.config :as config]
@ -14,7 +13,7 @@
(let [customization-color (rf/sub [:profile/customization-color]) (let [customization-color (rf/sub [:profile/customization-color])
[primary-name _] (rf/sub [:contacts/contact-two-names-by-identity contact-id])] [primary-name _] (rf/sub [:contacts/contact-two-names-by-identity contact-id])]
[rn/view [rn/view
[permission-context/view [quo/permission-context
[quo/button [quo/button
{:type :ghost {:type :ghost
:size 24 :size 24

View File

@ -1,7 +1,6 @@
(ns status-im2.contexts.contacts.drawers.nickname-drawer.view (ns status-im2.contexts.contacts.drawers.nickname-drawer.view
(:require (:require
[clojure.string :as string] [clojure.string :as string]
[quo.components.icon :as icons]
[quo.core :as quo] [quo.core :as quo]
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[react-native.core :as rn] [react-native.core :as rn]
@ -60,7 +59,7 @@
:on-submit-editing #(add-nickname-and-show-toast primary-name @entered-nickname public-key)}] :on-submit-editing #(add-nickname-and-show-toast primary-name @entered-nickname public-key)}]
[rn/view [rn/view
{:style style/nickname-description-container} {:style style/nickname-description-container}
[icons/icon :i/info [quo/icon :i/info
{:size 16 {:size 16
:color (colors/theme-colors colors/black colors/white)}] :color (colors/theme-colors colors/black colors/white)}]
[quo/text [quo/text

View File

@ -1,6 +1,5 @@
(ns status-im2.contexts.quo-preview.animated-header-list.animated-header-list (ns status-im2.contexts.quo-preview.animated-header-list.animated-header-list
(:require (:require
[quo.components.animated-header-flatlist.view :as animated-header-list]
[quo.core :as quo] [quo.core :as quo]
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[re-frame.core :as rf] [re-frame.core :as rf]
@ -83,4 +82,4 @@
(defn mock-screen (defn mock-screen
[] []
[animated-header-list/animated-header-list parameters]) [quo/animated-header-list parameters])