Skip to content

feat: Add profile screen and various improvements#10

Merged
digitalnomad91 merged 4 commits intomainfrom
feature/profile-screen-and-improvements
Feb 22, 2026
Merged

feat: Add profile screen and various improvements#10
digitalnomad91 merged 4 commits intomainfrom
feature/profile-screen-and-improvements

Conversation

@digitalnomad91
Copy link
Member

Summary

This PR adds a new Profile screen and various improvements to the app:

New Features

  • Profile screen with user information display
  • Google Sign Out and Revoke Access functionality
  • Permissions layout for better organization

Improvements

  • Add TypeScript types for react-native-console-view
  • Add misc utilities for time formatting (timeAgo function)
  • Add Gradle wrapper files for Android builds
  • Update tab layout to include Profile tab
  • Improve debug screen and login functionality
  • Update various permission demos

Removed

  • Deprecated cellular and location components

Dependencies

  • Update dependencies in package.json

Testing

  • Tested profile screen functionality
  • Verified Google Sign Out and Revoke Access features
  • Confirmed permissions layout works correctly

Note

This commit excludes:

  • scripts/adb-connect.sh
  • scripts/adb-connect2.sh

Copilot AI review requested due to automatic review settings February 22, 2026 07:40
- Add new Profile screen with user information display
- Add Google Sign Out and Revoke Access functionality
- Add permissions layout for better organization
- Add TypeScript types for react-native-console-view
- Add misc utilities for time formatting
- Add Gradle wrapper files for Android builds
- Update tab layout to include Profile tab
- Remove deprecated cellular and location components
- Improve debug screen and login functionality
- Update various permission demos
- Update dependencies in package.json
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new Profile screen and various improvements to the React Native app, including enhanced permission demos, better navigation patterns, and utility functions for time formatting.

Changes:

  • Added a Profile screen with Google authentication management (sign out/revoke access)
  • Significantly expanded permission demos for Telephony/SMS, Camera/Microphone, and Location
  • Added time formatting utilities (timeAgo function) and integrated into LogViewer
  • Refactored login flow to auto-redirect to profile when authenticated
  • Reorganized tab navigation, replacing "Cellular" tab with "Profile" tab
  • Fixed camera toggle bug and added better error handling for camera types

Reviewed changes

Copilot reviewed 23 out of 26 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
utils/misc.utils.ts New time formatting utilities with timeAgo and parseTimeString functions
utils/camera.utils.ts Fixed toggleCameraType bug and improved error handling for camera types
types/react-native-console-view.d.ts Added TypeScript type definitions for react-native-console-view
components/permissions/TelephonySmsPermissionDemo.tsx Major expansion with cellular info, contacts pagination, call logs, and SMS functionality
components/permissions/LocationPermissionDemo.tsx Integrated map display and location hook for better UX
components/permissions/CameraMicrophonePermissionDemo.tsx Expanded with live camera preview, controls, and capture functionality
components/permissions/NotificationsPermissionDemo.tsx Added trigger sample notification button
components/LogViewer.tsx Integrated timeAgo utility with auto-refresh every 30 seconds
components/CustomHeader.tsx Updated to use safe area insets for proper padding on notched devices
app/(tabs)/profile.tsx New profile screen with user information and authentication controls
app/login.tsx Refactored to auto-redirect authenticated users to profile
app/debug.tsx Enhanced with exception handler controls and crash test buttons
app/_layout.tsx Cleaned up by removing inline exception handlers
app/modal.tsx Updated to redirect to camera permissions instead of embedding camera
app/(tabs)/index.tsx Simplified home screen by removing location/map display
app/(tabs)/_layout.tsx Updated tab layout with Profile tab and improved permissions tab navigation
app/(tabs)/permissions/index.tsx Enhanced UI with icons, colors, and better navigation
app/(tabs)/permissions/_layout.tsx New layout file for permissions stack navigation
package.json Added expo-contacts and expo-sms dependencies
build/android/* Added Gradle wrapper files for Android builds

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +57 to +67
tabPress: (e: { preventDefault: () => void }) => {
// If already on a permissions sub-page (not the index), navigate to permissions index
const isOnPermissionsSubPage = pathname.startsWith('/permissions/') && pathname !== '/permissions';
const isOnPermissionsIndex = pathname === '/permissions' || pathname === '/(tabs)/permissions';

if (isOnPermissionsSubPage || isOnPermissionsIndex) {
// Prevent default tab behavior
e.preventDefault();
// Navigate to permissions index, replacing the current route to reset the stack
router.replace('/(tabs)/permissions');
}
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

The tab press logic on lines 59-62 has redundant conditions. When isOnPermissionsIndex is true, the code prevents default and calls router.replace('/(tabs)/permissions'), which navigates to the same page the user is already on. This creates unnecessary navigation and may cause flickering. The condition should only prevent default and navigate when on a sub-page, not when already on the index. Remove isOnPermissionsIndex from the if condition on line 62.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback

Comment on lines +10 to +50
export const timeAgo = (timestamp: Date | string | number): string => {
const now = new Date();
const date = timestamp instanceof Date ? timestamp : new Date(timestamp);

const diffMs = now.getTime() - date.getTime();
const diffSecs = Math.floor(diffMs / 1000);
const diffMins = Math.floor(diffSecs / 60);
const diffHours = Math.floor(diffMins / 60);
const diffDays = Math.floor(diffHours / 24);
const diffWeeks = Math.floor(diffDays / 7);
const diffMonths = Math.floor(diffDays / 30);
const diffYears = Math.floor(diffDays / 365);

if (diffSecs < 60) {
return '<1 min ago';
} else if (diffMins === 1) {
return '1 min ago';
} else if (diffMins < 60) {
return `${diffMins} mins ago`;
} else if (diffHours === 1) {
return '1 hour ago';
} else if (diffHours < 24) {
return `${diffHours} hours ago`;
} else if (diffDays === 1) {
return '1 day ago';
} else if (diffDays < 7) {
return `${diffDays} days ago`;
} else if (diffWeeks === 1) {
return '1 week ago';
} else if (diffWeeks < 4) {
return `${diffWeeks} weeks ago`;
} else if (diffMonths === 1) {
return '1 month ago';
} else if (diffMonths < 12) {
return `${diffMonths} months ago`;
} else if (diffYears === 1) {
return '1 year ago';
} else {
return `${diffYears} years ago`;
}
};
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

The timeAgo function doesn't handle future dates. If the timestamp is in the future (e.g., system clock issues or user-provided date), diffMs will be negative, causing incorrect "time ago" strings like "-5 mins ago". Consider adding a check at the beginning to handle future dates, either by returning "just now" or "in the future".

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +21
const diffMonths = Math.floor(diffDays / 30);
const diffYears = Math.floor(diffDays / 365);
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

The month calculation (diffDays / 30) and year calculation (diffDays / 365) use simplified assumptions that don't account for varying month lengths or leap years. For example, "1 month ago" could represent anywhere from 28-31 days. While this is acceptable for approximate "time ago" displays, consider documenting this limitation or using a more accurate date library like date-fns if precise calculations are needed.

Copilot uses AI. Check for mistakes.
Comment on lines 181 to 195
if (loadMore && contactsCursor) {
options.pageOffset = contactsCursor;
}

const { data, hasNextPage, hasPreviousPage } = await Contacts.getContactsAsync(options);

if (loadMore) {
setContacts(prev => [...prev, ...data]);
} else {
setContacts(data);
}

setHasMoreContacts(hasNextPage);
if (data.length > 0) {
setContactsCursor(data[data.length - 1].id);
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

The pagination implementation uses options.pageOffset = contactsCursor where contactsCursor is a contact ID (line 195). However, the expo-contacts API typically expects pageOffset to be a numeric index, not an ID. This may cause pagination to fail. Review the expo-contacts documentation for the correct pagination approach - you may need to use a numeric offset or a different pagination strategy.

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +37
// Exception handler callbacks
const jsExceptionHandler = (error: any, isFatal: boolean) => {
console.log('ExceptionHandler called with error: ', error, 'isFatal: ', isFatal);
};

const nativeExceptionHandler = (exceptionString: string) => {
console.log('Native ExceptionHandler called with exception: ', exceptionString);
};

const handleSetJSException = () => {
setJSExceptionHandler(jsExceptionHandler, true);
console.log('JS Exception Handler set!');
};

const handleGetJSException = () => {
const currentHandler = getJSExceptionHandler();
console.log('Current JS Exception Handler: ', currentHandler.toString());
};

const handleSetNativeException = () => {
setNativeExceptionHandler(nativeExceptionHandler, false, false);
console.log('Native Exception Handler set!');
};
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

The exception handlers (jsExceptionHandler and nativeExceptionHandler) are defined as module-level constants outside the component. While this works, calling setJSExceptionHandler or setNativeExceptionHandler multiple times will overwrite the global handlers each time. This is fine for a debug screen, but consider adding user feedback or checks to prevent redundant handler registration, or indicate to users that handlers are already set.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI commented Feb 22, 2026

@digitalnomad91 I've opened a new pull request, #11, to work on those changes. Once the pull request is ready, I'll request review from you.

digitalnomad91 and others added 3 commits February 22, 2026 02:01
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@digitalnomad91 digitalnomad91 merged commit 24003f4 into main Feb 22, 2026
4 checks passed
@digitalnomad91 digitalnomad91 deleted the feature/profile-screen-and-improvements branch February 22, 2026 08:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants