Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: refactor screens definitions and add more navigation events for screens #21328

Open
wants to merge 28 commits into
base: develop
Choose a base branch
from

Conversation

seanstrom
Copy link
Member

@seanstrom seanstrom commented Sep 26, 2024

Summary

  • This PR attempts to reorganise the definitions for all the app screens into separate groups
    • Ideally, these groups will help us selectively include more screens into the navigation tracking events.
    • Hopefully, grouping these screens will eventually lead to renaming screens to better describe their intent, and it could be nice to also use these groups for describing the "start" and "ends" of certain UX flows (from the code perspective).
    • Currently, this PR only extracts the existing definitions into separate groups, future work will begin leveraging these groups to help expand the navigation tracking.
  • The existing screens have been reviewed and documented, and we have some notes for mobile app screens that can be used as a reference for future work.

Updated Summary

  • This PR now decorates the screen definitions with extra metadata for configuring if the screen is tracked or not by analytics. The screens can also configure the name/id of the event that recorded when a user navigates to that screen.

Testing notes

  • There shouldn't be any breaking changes in this PR, but these changes do touch a core part of how the navigation system defines all of the screens that are accessible in the app. Meaning, that it could be important to do a regression test by navigating to "all the screens", or at least all of the major areas that could be affected like:
  • Settings
  • Wallet Settings
  • Wallet screens for an account, the send flow, the bridge flow, etc
  • Activity Center
  • Scanning QR codes
  • Contact Profiles
  • Syncing screens
  • Chat screens
  • Communities screens

Platforms

  • Android
  • iOS

Areas that maybe impacted

Functional
  • Navigation to any screen in the app

Steps to test

  • Open Status
  • Login into a profile
  • Navigate through any part of the app

Before and after screenshots comparison

WIP

status: ready

Risk

Described potential risks and worst case scenarios.

Tick one:

  • Low risk: 2 devs MUST perform testing as specified above and attach their results as comments to this PR before merging.
  • High risk: QA team MUST perform additional testing in the specified affected areas before merging.

@status-im-auto
Copy link
Member

status-im-auto commented Sep 26, 2024

Jenkins Builds

Click to see older builds (73)
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ bfc0646 #1 2024-09-26 07:49:33 ~4 min tests 📄log
✔️ bfc0646 #1 2024-09-26 07:51:06 ~6 min android-e2e 🤖apk 📲
✔️ bfc0646 #1 2024-09-26 07:52:50 ~8 min android 🤖apk 📲
✔️ bfc0646 #1 2024-09-26 07:57:19 ~12 min ios 📱ipa 📲
✔️ e74212c #2 2024-09-28 07:34:43 ~4 min tests 📄log
✔️ e74212c #2 2024-09-28 07:36:51 ~6 min android-e2e 🤖apk 📲
✔️ e74212c #2 2024-09-28 07:38:32 ~8 min android 🤖apk 📲
✔️ e74212c #2 2024-09-28 07:43:23 ~12 min ios 📱ipa 📲
✔️ 2357c20 #3 2024-09-28 08:04:10 ~4 min tests 📄log
✔️ 2357c20 #3 2024-09-28 08:06:11 ~6 min android-e2e 🤖apk 📲
✔️ 2357c20 #3 2024-09-28 08:06:56 ~6 min android 🤖apk 📲
✔️ 2357c20 #3 2024-09-28 08:16:19 ~16 min ios 📱ipa 📲
23aded7 #4 2024-09-30 12:01:20 ~2 min tests 📄log
✔️ 23aded7 #4 2024-09-30 12:05:55 ~7 min android 🤖apk 📲
✔️ 23aded7 #4 2024-09-30 12:06:07 ~7 min android-e2e 🤖apk 📲
✔️ 23aded7 #4 2024-09-30 12:07:04 ~8 min ios 📱ipa 📲
f78e205 #5 2024-09-30 12:50:31 ~2 min tests 📄log
✔️ f78e205 #5 2024-09-30 12:54:09 ~6 min android-e2e 🤖apk 📲
✔️ f78e205 #5 2024-09-30 12:54:24 ~6 min android 🤖apk 📲
✔️ f78e205 #5 2024-09-30 12:56:29 ~8 min ios 📱ipa 📲
1db00b3 #6 2024-09-30 13:20:28 ~2 min tests 📄log
✔️ 1db00b3 #6 2024-09-30 13:23:39 ~6 min android-e2e 🤖apk 📲
✔️ 1db00b3 #6 2024-09-30 13:25:17 ~7 min android 🤖apk 📲
✔️ 1db00b3 #6 2024-09-30 13:26:58 ~9 min ios 📱ipa 📲
4a85a0b #9 2024-10-01 08:12:32 ~2 min tests 📄log
✔️ 4a85a0b #9 2024-10-01 08:17:16 ~7 min android-e2e 🤖apk 📲
✔️ 4a85a0b #9 2024-10-01 08:17:34 ~7 min android 🤖apk 📲
✔️ 4a85a0b #9 2024-10-01 08:18:40 ~8 min ios 📱ipa 📲
2cf7918 #11 2024-10-01 17:16:15 ~3 min tests 📄log
✔️ 2cf7918 #11 2024-10-01 17:19:26 ~6 min android-e2e 🤖apk 📲
✔️ 2cf7918 #11 2024-10-01 17:20:45 ~7 min android 🤖apk 📲
✔️ 2cf7918 #11 2024-10-01 17:21:55 ~8 min ios 📱ipa 📲
070b6a1 #13 2024-10-02 12:35:28 ~2 min tests 📄log
✔️ 070b6a1 #13 2024-10-02 12:39:12 ~6 min android-e2e 🤖apk 📲
✔️ 070b6a1 #13 2024-10-02 12:39:26 ~6 min android 🤖apk 📲
✔️ 070b6a1 #13 2024-10-02 12:41:33 ~8 min ios 📱ipa 📲
549c9a3 #14 2024-10-02 14:09:40 ~2 min tests 📄log
✔️ 549c9a3 #14 2024-10-02 14:13:46 ~7 min android-e2e 🤖apk 📲
✔️ 549c9a3 #14 2024-10-02 14:14:33 ~7 min android 🤖apk 📲
✔️ 549c9a3 #14 2024-10-02 14:15:40 ~8 min ios 📱ipa 📲
c53d003 #15 2024-10-02 14:31:47 ~2 min tests 📄log
✔️ c53d003 #15 2024-10-02 14:36:49 ~7 min android 🤖apk 📲
✔️ c53d003 #15 2024-10-02 14:37:07 ~8 min android-e2e 🤖apk 📲
✔️ c53d003 #15 2024-10-02 14:37:53 ~8 min ios 📱ipa 📲
2ea6715 #16 2024-10-03 08:36:22 ~2 min tests 📄log
✔️ 2ea6715 #16 2024-10-03 08:40:12 ~6 min android-e2e 🤖apk 📲
✔️ 2ea6715 #16 2024-10-03 08:40:54 ~7 min android 🤖apk 📲
✔️ 2ea6715 #16 2024-10-03 08:42:46 ~8 min ios 📱ipa 📲
f19ca39 #17 2024-10-03 11:23:06 ~2 min tests 📄log
✔️ f19ca39 #17 2024-10-03 11:26:23 ~6 min android-e2e 🤖apk 📲
✔️ f19ca39 #17 2024-10-03 11:26:46 ~6 min android 🤖apk 📲
318454b #18 2024-10-03 11:30:52 ~2 min tests 📄log
8e92b36 #19 2024-10-03 11:36:46 ~3 min tests 📄log
bb8b199 #20 2024-10-03 11:41:43 ~2 min tests 📄log
✔️ bb8b199 #20 2024-10-03 11:45:02 ~6 min android-e2e 🤖apk 📲
✔️ bb8b199 #20 2024-10-03 11:45:52 ~6 min android 🤖apk 📲
✔️ bb8b199 #20 2024-10-03 11:48:39 ~9 min ios 📱ipa 📲
690dddc #21 2024-10-03 12:02:03 ~2 min tests 📄log
✔️ 690dddc #21 2024-10-03 12:05:19 ~6 min android-e2e 🤖apk 📲
✔️ 690dddc #21 2024-10-03 12:05:46 ~6 min android 🤖apk 📲
✔️ 690dddc #21 2024-10-03 12:10:49 ~11 min ios 📱ipa 📲
43856a8 #22 2024-10-03 15:50:50 ~3 min tests 📄log
✔️ 43856a8 #22 2024-10-03 15:54:06 ~6 min android-e2e 🤖apk 📲
✔️ 43856a8 #22 2024-10-03 15:54:52 ~7 min android 🤖apk 📲
✔️ 43856a8 #22 2024-10-03 15:56:39 ~8 min ios 📱ipa 📲
✔️ 181bcb5 #23 2024-10-03 16:08:24 ~4 min tests 📄log
✔️ 181bcb5 #23 2024-10-03 16:11:20 ~7 min android-e2e 🤖apk 📲
✔️ 181bcb5 #23 2024-10-03 16:11:29 ~7 min android 🤖apk 📲
✔️ 181bcb5 #23 2024-10-03 16:14:32 ~10 min ios 📱ipa 📲
✔️ 8c26c25 #24 2024-10-07 17:07:47 ~4 min tests 📄log
✔️ 8c26c25 #24 2024-10-07 17:10:13 ~7 min android-e2e 🤖apk 📲
✔️ 8c26c25 #24 2024-10-07 17:10:42 ~7 min android 🤖apk 📲
✔️ 8c26c25 #24 2024-10-07 17:14:35 ~11 min ios 📱ipa 📲
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ e5a11de #25 2024-10-07 19:49:12 ~5 min tests 📄log
✔️ e5a11de #25 2024-10-07 19:50:15 ~6 min android-e2e 🤖apk 📲
✔️ e5a11de #25 2024-10-07 19:52:29 ~8 min android 🤖apk 📲
✔️ e5a11de #25 2024-10-07 19:53:02 ~8 min ios 📱ipa 📲
✔️ 3c9fdb0 #26 2024-10-09 07:53:54 ~4 min tests 📄log
✔️ 3c9fdb0 #26 2024-10-09 07:55:26 ~6 min android-e2e 🤖apk 📲
3c9fdb0 #26 2024-10-09 07:57:12 ~7 min android 📄log
✔️ 3c9fdb0 #26 2024-10-09 07:58:53 ~9 min ios 📱ipa 📲

@ulisesmac
Copy link
Contributor

Hi @seanstrom

My thoughts on this PR:

I don't clearly see the problem we want to solve with this PR.

To me, some categories are not clearly defined: e.g.

  1. "Wallet" is a category with lots of screens, could they've been defined into smaller subcategories? what is the criteria to define a categroy? 🤔
  2. IMO "Community" should also contain screens defined in the "Chat" category, since in the app we can get to a chat through a community too.

Since I don't see a clear definition of the categories, I think the current PR provides the same clarity as what we had achieved only with comments before (i.e. ;; Wallet, ;; Wallet Settings, ;; Onboarding, ...).

On the other hand, I think it'd be great that our screens were grouped, ideally (to me), our file structure and our screen groups should reflect in some way the navigation structure, so that adding/organizing/finding a screen is easy.

future work will begin leveraging these groups to help expand the navigation tracking.

Is it possible for you to share the plans on how to achieve it?
Why not to implement them in this PR or at least make a small proposal and, if liked/approved by others, continue the work?


Sorry if I did a lot of questions, It's just a bit unclear to me the benefits from this PR.

Thanks @seanstrom !

@seanstrom
Copy link
Member Author

Hey @ulisesmac, these are good questions, thanks for the review 🙏

This PR is attempting to group the different screens into separate functions, but as you have mentioned they're not a precise enough abstraction over all of the screens. That being said the main benefit for grouping them into these "zones" will help with detecting which "kind" of screens is being displayed when we're tracking the navigation events.

For example, if we want to track more screen navigation events, but we want to be careful about which screens we're tracking, then we can reference a group of screens directly and extract the names of the screens. Here's some example code of what I'm thinking would be done in practice:

;; screen definitions

(defn contact-screens
  []
  [{:name      :new-contact
    :options   {:sheet? true}
    :component add-new-contact/new-contact}

   {:name      :scan-profile-qr-code
    :options   options/dark-screen
    :component scan-profile-qr-page/view}

   {:name      :contact-profile
    :options   {:modalPresentationStyle :overCurrentContext}
    :component contact-profile/view}

   {:name      :share-contact
    :options   options/transparent-screen-options
    :component share-contact/view}])

(defn onboarding-screens
  []
  [{:name      :screen/onboarding.intro
    :options   {:theme :dark}
    :on-focus  [:onboarding/overlay-dismiss]
    :component intro/view}

   {:name      :screen/onboarding.syncing-results
    :options   {:theme :dark}
    :component syncing-results/view}])
      
;; tracking

(def ^:const view-ids-to-track
  (-> (concat (onboarding-screens) (contact-screens))
      (map :name)
      (into #{;; Tabs
              :communities-stack
              :chats-stack
              :wallet-stack})))

(defn track-view-id-event
  [view-id]
  (when (contains? view-ids-to-track view-id)
    (navigation-event (name view-id))))

(defn tracked-event
  [[event-name second-parameter]]
  (case event-name
    :profile/get-profiles-overview-success
    (user-journey-event app-started-event)

    :centralized-metrics/toggle-centralized-metrics
    (key-value-event "events.metrics-enabled" :enabled second-parameter)

    :set-view-id
    (track-view-id-event second-parameter)

    nil))

In this example we can see that the tracking code is now referencing the screen names without duplicating the names from the screens file, and it also helps us focus a specific subset of screens. And if we can focus on a subset then we can add additional metadata or logic for processing those navigation events, or even limit the amount of metadata when we think the event could represent sensitive information (like a wallet transaction or something).

To me, some categories are not clearly defined: e.g.

  1. "Wallet" is a category with lots of screens, could they've been defined into smaller subcategories? what is the criteria to define a categroy? 🤔
  2. IMO "Community" should also contain screens defined in the "Chat" category, since in the app we can get to a chat through a community too.
  1. Yeah absolutely! I also think we should define smaller subsets for the wallet screens, especially since we may want to track certain features like swaps or wallet-connect in different ways.
  2. Yeah good point about the names of screens being shared across features. This is a tricky problem to contend with since we may want to identify when someone opens a community channel chat vs a messenger chat. There might be a way of doing this by inferring metadata from the app-state, but maybe we can create some extra screen aliases.
    • For example, maybe we can define a new screen like :screen/community.channel, and that would point to the same chat component, but we can reference the more distinct name when tracking the navigation event.

On the other hand, I think it'd be great that our screens were grouped, ideally (to me), our file structure and our screen groups should reflect in some way the navigation structure, so that adding/organizing/finding a screen is easy.

Yeah this would be an ideal for me too, though I haven't attempted to re-structure things atm. For now I'm relying on the screens file to be source-of-truth for all the screen names.

Is it possible for you to share the plans on how to achieve it?
Why not to implement them in this PR or at least make a small proposal and, if liked/approved by others, continue the work?

Yeah we can continue to improve this PR to have better groups or aliases for the screens, atm I decided to try something minimal with low-risk of breaking things, but we can continue to refine this approach in this PR or as we go. Though I did plan to experiment with the tracking code in a separate PR when we start expanding the navigation events, but I suppose we can at least replace the onboarding detection and possibly add more screens to the tracking logic too.


I hope this commentary helps clarify things, and feel free to share more too. I imagine that this will be a collective effort for managing screens over time, so we should have something that we can all maintain and enjoy 🙌

@ilmotta
Copy link
Contributor

ilmotta commented Sep 27, 2024

@seanstrom: Grouping screens in different vars is a nice improvement, I see no harm in that, but using that as a proxy for meaning trackable I think is mixing orthogonal concerns. It will cause trouble later because we will need to regroup screens to indirectly track/not track them.

A more direct solution, which also doesn't rely on hierarchies is: we can add a flag to each navigation screen map in case it is allowed to be tracked. Then, in the tracking namespace, similar to what you shared above, we statically build a set of view-ids-to-track. We could do the opposite to build a blocklist too, but the allowlist would be slightly safer to avoid the case of tracking new screens by mistake (a dev can easily forget to disable if the default is to track).

The code would be trivial:

{:name      :screen/xyz
 :track?    true ; => ********* ADDED
 :options   {:insets {:top? true}}
 :component ...}

;; In the ns status-im.contexts.centralized-metrics.tracking
(def ^:const view-ids-to-track
  (into #{;; Tabs
          :communities-stack
          :chats-stack
          :wallet-stack}
        (->> (screens/screens)
             (filter :track?)
             (map :name))))

About the discussion of code organization of the screens, I kind of prefer a central place than spreading them over directories, which would make finding them even more difficult, just 2 cents.

One thing that's been on my radar for a long time was to extract each screen map into a separate var because that would instantly give us reference finding, unused screens, and jumping to source. Would be super helpful to everybody if we did this 🙊

Copy link
Contributor

@ulisesmac ulisesmac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ilmotta @seanstrom
After considering your points, I'm approving this PR now since I agree on the benefit of tracking data.

And, just to clarify, ideally, I'd like to have a Clojure data structure and a file hierarchy that refelects the navigation:

e.g. for files

root
|
|--- Onboarding
         |
         |--- Welcome
         |--- Sign-in
|
|--- Wallet
        |
        |-- Home
|
|--- Communities
|--- Messsages
|--- Browser

Something similar to [Expo Router (used for React Native)](Introduction to Expo Router)

It brings the best file-system routing concepts from the web to a universal application — allowing your routing to work across every platform. When a file is added to the app directory, the file automatically becomes a route in your navigation.

So it'd impact our (defn screens [] ...), we could even create a macro to do the job, but we first need to make clear what is the best data structure.

@seanstrom seanstrom force-pushed the seanstrom/chore-refactor-screens-definitions branch from bfc0646 to e74212c Compare September 28, 2024 07:30
@seanstrom
Copy link
Member Author

@ilmotta @ulisesmac thanks for the feedback 🙏

I agree that we should add more data to each screen for configuring :trackable?. That idea makes me think we could even create a :metrics key for each screen that could contain as much metadata as we need over time.

@seanstrom seanstrom force-pushed the seanstrom/chore-refactor-screens-definitions branch from 2357c20 to 23aded7 Compare September 30, 2024 11:57
@seanstrom
Copy link
Member Author

Okay I've made some changes based on some experiments and your feedback. Now we can configure if a screen is tracked by tagging the screen definition with some extra metadata, and we can also alias the event-id / event name that gets sent to Mixpanel too. We also have the ability to send screen specific events (if we want to), please let me know what you think when you have a chance 🙏

cc @ilmotta @ulisesmac

@ilmotta
Copy link
Contributor

ilmotta commented Oct 1, 2024

Something similar to [Expo Router (used for React Native)](Introduction to Expo Router)

It brings the best file-system routing concepts from the web to a universal application — allowing your routing to work across every platform. When a file is added to the app directory, the file automatically becomes a route in your navigation.

So it'd impact our (defn screens [] ...), we could even create a macro to do the job, but we first need to make clear what is the best data structure.

@ulisesmac This reminds of the way Rails made convention over configuration famous more than 15 years ago 🚋 I tend to prefer more explicit configuration, rather than implicit because it's simpler to accommodate for pretty much any use case. But I don't have any strong preference, but other CCs may have.

Copy link
Contributor

@ilmotta ilmotta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm leaving a few minor suggestions @seanstrom. As usual, great work with the thoughtful implementation.

src/status_im/contexts/centralized_metrics/tracking.cljs Outdated Show resolved Hide resolved
@@ -0,0 +1,10 @@
{
"folders": [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checking, is this file being intentionally added? Good for other devs too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ooops, this is my special file 🙈

@@ -17,7 +17,10 @@
(when-let [event (tracking/tracked-event (interceptor/get-coeffect context :event))]
(log/debug "tracking event" event)
(when (push-event? (interceptor/get-coeffect context :db))
(native-module/add-centralized-metric event)))
(cond
(and (coll? event)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@seanstrom, coll? will return true if event is a map, for example. Maybe here we should only use vector? to be extra precise?

Could be an if instead of cond. doseq is preferred to process with side-effects and ignore results.

(if (vector? event)
  (doseq [e event]
    (native-module/add-centralized-metric e))
  (native-module/add-centralized-metric event))

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah good call for using doseq 👍

I think you're right that we can remove the coll? check. Additionally, I think we can also support seqs by using seq? since we might return a sequence or vector from the tracking function, how does that sound?

(defn community-screens
[]
[{:name :discover-communities
:metrics {:flow :community
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm on the fence about adding :flow now because we aren't using this data yet, or maybe I missed in the diff. Given that event.id keyword already has a useful qualification, in the analytics tool this may be sufficient for filtering purposes (not sure).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to remove these values 👍

For context: currently :flow is not used for anything, so we do not need that property, it's mostly there as a way to categorise the screens without relying too much on the variable names in the file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for removing them, since we are already categorizing them with vars

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also feel we should not add it here. Flow can be inferred from the data.

Copy link
Member Author

@seanstrom seanstrom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self-Review 📓

src/status_im/contexts/centralized_metrics/events.cljs Outdated Show resolved Hide resolved
src/status_im/contexts/centralized_metrics/tracking.cljs Outdated Show resolved Hide resolved
src/status_im/contexts/centralized_metrics/tracking.cljs Outdated Show resolved Hide resolved
@@ -0,0 +1,10 @@
{
"folders": [
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ooops, this is my special file 🙈

@seanstrom seanstrom force-pushed the seanstrom/chore-refactor-screens-definitions branch 2 times, most recently from e116aaf to 50d6a32 Compare October 1, 2024 08:07
@seanstrom seanstrom force-pushed the seanstrom/chore-refactor-screens-definitions branch from 7e1b94d to 2cf7918 Compare October 1, 2024 17:12
@seanstrom seanstrom changed the title chore: refactor screens definitions into groups chore: refactor screens definitions and add more navigation events for screens Oct 2, 2024
@seanstrom seanstrom force-pushed the seanstrom/chore-refactor-screens-definitions branch from 2cf7918 to a0ac154 Compare October 2, 2024 12:30
src/status_im/contexts/centralized_metrics/tracking.cljs Outdated Show resolved Hide resolved
src/status_im/contexts/centralized_metrics/tracking.cljs Outdated Show resolved Hide resolved
src/status_im/navigation/screens.cljs Outdated Show resolved Hide resolved
(defn community-screens
[]
[{:name :discover-communities
:metrics {:flow :community
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for removing them, since we are already categorizing them with vars

Copy link
Member

@clauxx clauxx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@seanstrom seanstrom force-pushed the seanstrom/chore-refactor-screens-definitions branch from e5a11de to 3c9fdb0 Compare October 9, 2024 07:49
@mariia-skrypnyk
Copy link

Hey @seanstrom !

Is PR ready to be tested? Or you plan to do more changes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: IN TESTING
Status: Code Review
Development

Successfully merging this pull request may close these issues.

7 participants