Skip to content

Commit

Permalink
feat: User can invite other device to a project (#79)
Browse files Browse the repository at this point in the history
* created initial screens

* more invite screen

* translations

* finished screens

* chore: integrate api, and discovery hook

* chore: integrated api for invite

* chore: ui changes

* chore: updated invite state management

* chore: patch-package for mapeo/core discovery

* chore: styling

* chore: update styling

* fix: ipc timeout removed

* chore: updated component to encapsulate 2 screens

* chore:translations

* chore:update @mapeo/ipc to @latest

* chore:remove memoization

* chore: remove unnecessary undefined check

* chore: remove unnecessary console logs

* chore:track mounting of screen so promise does not always get resolved

* Revert "chore:track mounting of screen so promise does not always get resolved"

This reverts commit 7fc1ed2.

* chore:translations
  • Loading branch information
ErikSin authored Feb 8, 2024
1 parent 95f5762 commit 8eec84a
Show file tree
Hide file tree
Showing 28 changed files with 1,191 additions and 30 deletions.
99 changes: 99 additions & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,39 @@
"Screens.Settings.ProjectSettings.yourTeam": {
"message": "Your Team"
},
"screen.Settings.ProjectSettings.YourTeam.ReviewAndInvite.ReviewInvitation.coordinator": {
"message": "Coordinator"
},
"screen.Settings.ProjectSettings.YourTeam.ReviewAndInvite.ReviewInvitation.participant": {
"message": "Participant"
},
"screen.Settings.ProjectSettings.YourTeam.ReviewAndInvite.ReviewInvitation.sendInvite": {
"message": "Send Invite"
},
"screen.Settings.ProjectSettings.YourTeam.SelectDevice.notSeeingDevice": {
"message": "Not seeing a Device?"
},
"screen.Settings.ProjectSettings.YourTeam.SelectDevice.sameVersion": {
"message": "Make sure both devices are on the same version of Mapeo"
},
"screen.Settings.ProjectSettings.YourTeam.SelectDevice.sameWifi": {
"message": "Make sure both devices are on the same wifi network"
},
"screen.Settings.ProjectSettings.YourTeam.SelectDevice.title": {
"message": "Select Device to Invite"
},
"screen.Settings.ProjectSettings.YourTeam.SelectInviteeRole.coordinatorDescription": {
"message": "As a Coordinator this device can invite and remove users, and manage project details."
},
"screen.Settings.ProjectSettings.YourTeam.SelectInviteeRole.participantDescription": {
"message": "As a Participant this device can take and share observations. They cannot manage users or project details."
},
"screen.Settings.ProjectSettings.YourTeam.SelectInviteeRole.selectingDevice": {
"message": "You are selecting a role for this device:"
},
"screen.Settings.ProjectSettings.YourTeam.SelectInviteeRole.title": {
"message": "Select a Role"
},
"screens.AddPhoto.cancel": {
"message": "Cancel"
},
Expand Down Expand Up @@ -99,6 +132,9 @@
"message": "This passcode will be required to open the Mapeo App"
},
"screens.AppPasscode.NewPasscode.InputPasscodeScreen.title": {
"message": "Confirm Passcode"
},
"screens.AppPasscode.NewPasscode.SetPasscodeScreen.title": {
"message": "Set Passcode"
},
"screens.AppPasscode.NewPasscode.Splash.continue": {
Expand Down Expand Up @@ -357,6 +393,57 @@
"screens.Security.title": {
"message": "Security"
},
"screens.Setting.ProjectSettings.YourTeam.InviteAccepted.addAnotherDevice": {
"message": "Add Another Device"
},
"screens.Setting.ProjectSettings.YourTeam.InviteAccepted.close": {
"message": "Close"
},
"screens.Setting.ProjectSettings.YourTeam.InviteAccepted.inviteAccepted": {
"message": "Invite Accepted"
},
"screens.Setting.ProjectSettings.YourTeam.ReviewAndInvite.ReviewInvitation.title": {
"message": "Review Invitation"
},
"screens.Setting.ProjectSettings.YourTeam.ReviewAndInvite.ReviewInvitation.youAreInviting": {
"message": "You are inviting:"
},
"screens.Setting.ProjectSettings.YourTeam.ReviewAndInvite.title": {
"message": "Review Invitation"
},
"screens.Setting.ProjectSettings.YourTeam.WaitingForInviteAccept.cancelInvite": {
"message": "Cancel Invite"
},
"screens.Setting.ProjectSettings.YourTeam.WaitingForInviteAccept.timerMessage": {
"message": "Invite sent {seconds}s ago"
},
"screens.Setting.ProjectSettings.YourTeam.WaitingForInviteAccept.waitingMessage": {
"message": "Waiting for Device to Accept Invite"
},
"screens.Setting.ProjectSettings.YourTeam.coordinatorDescription": {
"message": "Coordinators can invite devices, edit and delete data, and manage project details."
},
"screens.Setting.ProjectSettings.YourTeam.coordinators": {
"message": "Coordinators"
},
"screens.Setting.ProjectSettings.YourTeam.dateAdded": {
"message": "Date Added"
},
"screens.Setting.ProjectSettings.YourTeam.deviceName": {
"message": "Device Name"
},
"screens.Setting.ProjectSettings.YourTeam.inviteDevice": {
"message": "Invite Device"
},
"screens.Setting.ProjectSettings.YourTeam.participantDescription": {
"message": "Participants can take and share observations. They cannot manage users or project details."
},
"screens.Setting.ProjectSettings.YourTeam.participants": {
"message": "Participants"
},
"screens.Setting.ProjectSettings.YourTeam.title": {
"message": "Your Team"
},
"screens.Settings.CreateOrJoinProject.CreateProject.title": {
"message": "Create a Project"
},
Expand Down Expand Up @@ -446,6 +533,12 @@
"description": "Title of settings screen",
"message": "Settings"
},
"sharedComponents.DeviceCard.ThisDevice": {
"message": "This Device!"
},
"sharedComponents.DeviceIconWithName.thisDevice": {
"message": "This Device!"
},
"sharedComponents.ErrorModal.goBack": {
"message": "Go Back"
},
Expand All @@ -455,6 +548,12 @@
"sharedComponents.ErrorModal.tryAgain": {
"message": "Please go back and try again"
},
"sharedComponents.RoleWithIcon.coordinator": {
"message": "Coordinator"
},
"sharedComponents.RoleWithIcon.participant": {
"message": "Participant"
},
"sharedComponents.WifiBar.noWifi": {
"message": "No Internet"
},
Expand Down
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"@formatjs/intl-pluralrules": "^5.2.4",
"@formatjs/intl-relativetimeformat": "^11.2.4",
"@gorhom/bottom-sheet": "^4.5.1",
"@mapeo/ipc": "^0.1.3",
"@mapeo/ipc": "^0.1.5",
"@react-native-community/hooks": "^2.8.0",
"@react-native-community/netinfo": "^9.4.1",
"@react-native-picker/picker": "^2.0.0",
Expand Down
16 changes: 8 additions & 8 deletions src/backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"license": "MIT",
"dependencies": {
"@mapeo/core": "9.0.0-alpha.4",
"@mapeo/ipc": "^0.1.3",
"@mapeo/ipc": "^0.1.5",
"debug": "^4.3.4"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,68 @@ index d4cfdfd..41cc2db 100644
+import quickbit from 'quickbit-universal'

export { quickbit }
diff --git a/node_modules/@mapeo/core/src/discovery/dns-sd.js b/node_modules/@mapeo/core/src/discovery/dns-sd.js
index 677006d..707ae35 100644
--- a/node_modules/@mapeo/core/src/discovery/dns-sd.js
+++ b/node_modules/@mapeo/core/src/discovery/dns-sd.js
@@ -35,18 +35,30 @@ export class DnsSd extends TypedEmitter {
#error = null
/** @param {import('bonjour-service').Service} service */
#handleServiceUp = (service) => {
+ this.#log(service.addresses, 'addresses')
+ this.#log(service.port, 'port')
+ this.#log(service, "service")
+
if (service.name === this.#name) {
this.#log(`Ignoring service up from self`)
return
}
- const address = service.addresses?.filter(isIpv4)[0]
- /* c8 ignore start */
- if (!address) {
- this.#log(`service up (${service.name}) with no ipv4 addresses`)
+ // const address = service.addresses?.filter(isIpv4)[0]
+ const { name, port, referer } = service
+ if (!referer) {
+ this.#log(`service up (${service.name}) had no referer`)
return
}
+
+ const { address } = referer
+
+ /* c8 ignore start */
+ // if (!address) {
+ // this.#log(`service up (${service.name}) with no ipv4 addresses`)
+ // return
+ // }
/* c8 ignore stop */
- const { name, port } = service
+ // const { name, port } = service
this.#log('serviceUp', name.slice(0, 7), address, port)
this.emit('up', { port, name, address })
}
@@ -67,7 +79,7 @@ export class DnsSd extends TypedEmitter {
this.#log(`service down`, [name, address, port])
this.emit('down', { port, name, address })
}
- #disableIpv6
+ #disableIpv6 = false
/** @type {Promise<any> | null} */
#advertisingStarting = null
/** @type {Promise<any> | null} */
@@ -79,14 +91,12 @@ export class DnsSd extends TypedEmitter {
*
* @param {object} [opts]
* @param {string} [opts.name]
- * @param {boolean} [opts.disableIpv6]
* @param {Logger} [opts.logger]
*/
- constructor({ name, disableIpv6 = true, logger } = {}) {
+ constructor({ name, logger } = {}) {
super()
this.#l = Logger.create('dnssd', logger)
this.#name = name || randomBytes(8).toString('hex')
- this.#disableIpv6 = disableIpv6
this.#log = this.#l.log.bind(this.#l)
}

2 changes: 1 addition & 1 deletion src/frontend/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {

const queryClient = new QueryClient();
const messagePort = new MessagePortLike();
const mapeoApi = createMapeoClient(messagePort);
const mapeoApi = createMapeoClient(messagePort, {timeout: Infinity});
const localDiscoveryController = createLocalDiscoveryController({
startLocalPeerDiscovery() {
return mapeoApi.startLocalPeerDiscovery();
Expand Down
47 changes: 47 additions & 0 deletions src/frontend/Navigation/ScreenGroups/AppScreens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ import {CreateOrJoinProject} from '../../screens/Settings/CreateOrJoinProject';
import {CreateProject} from '../../screens/Settings/CreateOrJoinProject/CreateProject';
import {ProjectCreated} from '../../screens/Settings/CreateOrJoinProject/CreateProject/ProjectCreated';
import {JoinExistingProject} from '../../screens/Settings/CreateOrJoinProject/JoinExistingProject';
import {YourTeam} from '../../screens/Settings/ProjectSettings/YourTeam';
import {SelectDevice} from '../../screens/Settings/ProjectSettings/YourTeam/SelectDevice';
import {DeviceRole, DeviceType} from '../../sharedTypes';
import {SelectInviteeRole} from '../../screens/Settings/ProjectSettings/YourTeam/SelectInviteeRole';
import {ReviewInvitation} from '../../screens/Settings/ProjectSettings/YourTeam/ReviewAndInvite/ReviewInvitation';
import {InviteAccepted} from '../../screens/Settings/ProjectSettings/YourTeam/InviteAccepted';
import {ReviewAndInvite} from '../../screens/Settings/ProjectSettings/YourTeam/ReviewAndInvite';

export type HomeTabsList = {
Map: undefined;
Expand Down Expand Up @@ -90,6 +97,21 @@ export type AppList = {
CreateOrJoinProject: undefined;
ProjectCreated: {name: string};
JoinExistingProject: undefined;
YourTeam: undefined;
SelectDevice: undefined;
SelectInviteeRole: {name: string; deviceType: DeviceType; deviceId: string};
ReviewAndInvite: {
name: string;
deviceType: DeviceType;
deviceId: string;
role: DeviceRole;
};
InviteAccepted: {
name: string;
deviceType: DeviceType;
deviceId: string;
role: DeviceRole;
};
};

const Tab = createBottomTabNavigator<HomeTabsList>();
Expand Down Expand Up @@ -233,5 +255,30 @@ export const createDefaultScreenGroup = (
component={JoinExistingProject}
options={{headerShown: false}}
/>
<RootStack.Screen
name="YourTeam"
component={YourTeam}
options={{headerTitle: intl(YourTeam.navTitle)}}
/>
<RootStack.Screen
name="SelectDevice"
component={SelectDevice}
options={{headerTitle: intl(SelectDevice.navTitle)}}
/>
<RootStack.Screen
name="SelectInviteeRole"
component={SelectInviteeRole}
options={{headerTitle: intl(SelectInviteeRole.navTitle)}}
/>
<RootStack.Screen
name="ReviewAndInvite"
component={ReviewAndInvite}
options={{headerTitle: intl(ReviewInvitation.navTitle)}}
/>
<RootStack.Screen
name="InviteAccepted"
component={InviteAccepted}
options={{headerShown: false}}
/>
</RootStack.Group>
);
10 changes: 10 additions & 0 deletions src/frontend/hooks/server/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,13 @@ export function useCreateProject() {
},
});
}

export function useProjectMembers() {
const project = useProject();
return useQuery({
queryFn: async () => {
return await project.$member.getMany();
},
queryKey: ['projectMembers'],
});
}
Loading

0 comments on commit 8eec84a

Please sign in to comment.