Merge main into production (#4437)

* 3871 activity session issues feedback (#3874)

* fix: add header when fetching image from CMS

* fix: only show activity start page is all roles have never been full

* chore: disable archive button until summary loads

* chore: still save activity analytics summary even if there's a choreo error when fetching summary

* chore: pass location image URL as topic image URL (#3876)

* feat: add local cache for activity session analytics (#3878)

* fix: in new courses, set course_user state event power level to 0 (#3882)

* fix: make activity summary request cache keys unique, use in-memory cache instead of local storage, remove items from cache on error or on state event sent successfully (#3885)

* chore: widen summary cards (#3888)

* Replaced references to spaces with courses in intl files and calls (#3884)

* Replaced references to spaces with courses in intl files and calls

* Change learning community reference to 'public course'

---------

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* chore: update delete course description (#3889)

* 3890 activity start page changes (#3901)

* comment out unreferenced files

* decouple courses, topics, and activities

* update start page

* disable 'join open session' button

* feat: activity dropdown menu

* fix: always initialize course info after fetching (#3907)

* chore: show role goal in text abut button on activity launch page and in tooltip above input bar (#3910)

* chore: go to course settings tab after archiving activity, show check over completed activites (#3913)

* fix: remove dollar sign from copy (#3914)

* fix: update payload accessToken on new login (#3916)

* 3915 course chat view updates (#3919)

* Removes Proper Noun from default analytics morph list (#3918)

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* Level up popup tweaks (#3917)

* Use L10n for 'Level up' text

* Replace drop down button with close button

---------

Co-authored-by: ggurdin <ggurdin@gmail.com>
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* chore: update how activity summary description expansion button layout works (#3930)

* fix: add analytics listener to activity stats menu (#3931)

* fix: don't show join message when user dismisses activity role goal message (#3932)

* chore: hide activity role tooltip when it bar is open (#3933)

* fix: fix null check error in activity role tooltip (#3935)

* fix: when fetching translation, only consider a message to have included IT if the sent message body matches the message at the end of choreo (#3936)

* chore: update messaging in subscription management (#3937)

* feat: join activity session on open app via ping (#3944)

* chore: don't show ping unread badge (#3946)

* fix: Correctly fetch activity images (#3943)

* fix fetching images and parsing url

* small fix for getting activity image URLs

---------

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>
Co-authored-by: ggurdin <ggurdin@gmail.com>

* Set thumbVisibility true for grammar activity scrolling (#3942)

* Set thumbVisibility true for grammar activity scrolling

* always show scrollbar

---------

Co-authored-by: ggurdin <ggurdin@gmail.com>
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* reload space hierarchy on invite update (#3949)

* 3927 analytics tweaks (#3953)

* analytics page updates

* add back download buttons

* some activity / invite page tweaks (#3958)

* Wrap invite course avatar in MapClipper (#3957)

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* Add period to end of languageLevelA2Desc (#3959)

* fix: put back pangea controller init in chat list (#3965)

* fix: show bot avatar in open roles indicator (#3966)

* fix: on cancel registration, pop future loading dialog (#3967)

* chore: adjust actvity participant text colot (#3968)

* fix: always reload course on ID change (#3969)

* chore: increase size of text in archived activity popup (#3970)

* feat: add edit course page (#3971)

* 3962 usability test todos (#3973)

* in new course pages, show images

* in space analytics, if no available languages, pick user's l2

* chore: add cooldown on ping participants

* replace image loading icon with shimmer

* update activity launch page buttons, sort activities in topics by number of participants (#3974)

* chore: topic is completed if user has finished number of activities equal to number of 2 person activities in topic (#3983)

* feat: always show new tokens with green underlines (#3984)

* 3873 add superlatives for most vocab grammar and xp (#3977)

* add grammar and vocab superlatives

- adds superlatives to the summary cards for each user
- WIP, doesn't include XP superlative yet and it continuously reinitializes state which reloads the superlatives

* get analytic superlatives from saved state event

Revert activity user summaries widget to stateless, get info from saved state event instead of awaiting it, and fix some spacing issues.

* add xp superlative

- simplify 3 loop logic into one
- change from constant updates to only generate superlatives on analytics save

* sort imports

* put analytics loading inside buttonControlledCarouselView

* delete commented out code

* return superlative map instead of setting value

* chore: on new token update, clear whole new token cache in case there are identical tokens (#3985)

* fix: fix calculation of completed activities (#3986)

* chore: collection seed always fades up and out (#3987)

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* 3988 activitycourse tweaks (#3989)

* chore: set course and activity descriptions

* chore: remove redundant results button

* 3921 display unsubscribed errors for users (#3991)

* url cleanup

* chore: display unsubscribed errors differently

* chore: show user menu on click participant item (#3992)

* fix: Reintroduce shared isolate (#3981)

* initial scripts n actions

* custom cshared isolate

* kitlin fixes

* integrate and token fix

* executable and gstreamer

* disable check dupes, fix gstreamer

* another linux update, removed 2 android builds

* new updates

* final android attempt

* formatting

---------

Co-authored-by: ggurdin <ggurdin@gmail.com>

* chore: add snackbar message after pinging course participants (#3995)

* fix: don't show green underlines on own messages (#3997)

* 3803 indented bullets displayed strangely (#3999)

* make markdown function the same as matrix sdk

* fix: fix newline issues in html messages

* fix: replace build-web script (#4000)

* fix: try to fix build again (#4001)

* chore: don't allow hover of non-selectable activity participants items (#4002)

* 3895 emoji sequence on clicking the words in a sentence of the target language (#4004)

* cleanup

* feat: toolbar emoji mode

* Add dark/light mode check for unassigned participant label color (#4006)

* chore: update emoji button color (#4015)

* chore: move analytics tooltips inside scrollviews (#4016)

* chore: update icon and border of find a course nav rail item (#4005)

* chore: Improve translation script and translate vi, es, et (#3555)

* improve translation script

* update translation script, more translates for es, et, vi

* chore: fix click cursor showing on hover of disabled activity participant widget (#4020)

* chore: add hint text to text fields in course edit page (#4022)

* chore: add placeholder to image in course editting page (#4024)

* chore: show snackbar on course edit save (#4025)

* 4017 usability test todos 91725 (#4026)

* chore: add ability to toggle show password in signup and login pages

* chore: update text in register popup

* chore: disable save edits button if no changes in course edit page (#4033)

* chore: don't animate in-chat tooltips (#4034)

* chore: add scrollbar to topic activities list (#4035)

* Morph analytics scroll (#4032)

* Move download button above scroll view

* Make morph analytics spacing consistent with vocab analytics spacing

* feat: add ability to add course to existing space (#4037)

* fix: don't attempt to load analytics until your is logged in (#4047)

* feat: integrate room preview endpoint (#4014)

* feat: integrate room preview endpoint

* initial work for intermediary activity page

* Update lib/pangea/activity_sessions/activity_session_start/activity_session_start_page.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update lib/pangea/activity_sessions/activity_session_start/activity_session_start_page.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update lib/pangea/chat_settings/utils/room_summary_extension.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* formatting

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* 3934 activity summary card visual changes (#4013)

* visual tweaks and confetti rain on results generation

* create star rain widget to trigger when activity finishes

* delete commented out lines

* use new star confetti widget in levelup

---------

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* Set height of activity creation sized box to 0 (#4048)

* 4036 playtest 91825 (#4051)

* chore: improve constrast in message practice

* fix typo

* chore: disable learning settings save button until change is made

* show word card on click vocab in activity dropdown

* Playtest updates (#4054)

* update emoji mode icon and tooltip

* upload CMS url instead of uploading image bytes to matrix

* re-init subscription controller after setting account creation date

* fix: don't allow new users to steal roles (#4055)

* chore: render activity instruction markdown (#4056)

* chore: disable hover effect on loading span card icons (#4057)

* fix: fix needed participants copy (#4058)

* update course plan repo search to correctly query (#4065)

* chore: fix practice mode icon / border contrast (#4067)

* chore: only show emoji button for save-vocab tokens, fix alignment for non-token text (#4071)

* fix: fix button visibility in activity start page (#4073)

* chore: use synapse room_preview to determine which activities users have completed (#4078)

* fix: don't reset edits using the room's title and description (#4080)

* chore: on web, show analytics in course chat view (#4085)

* chore: show user menu on click avatar in topic participant list (#4086)

* fix: fix toolbar buttons on mobile (#4087)

* chore: on course load error, show option to add a different course plan to space (#4089)

* fix: check if can invite to course when deciding if show invite button in activity session in course without enough users, disable instead of hiding (#4095)

* chore: shuffle practice tokens before selecting the ones to include (#4097)

* feat: show instruction overlay on first gain points in activity pointing user to click activity stats button (#4099)

* chore: add descriptions for analytics categories (#4100)

* chore: fix copy issue (#4102)

* fix: make invite button go to course invite page (#4103)

* chore: make autoIGC true for new accounts (#4105)

* 4110 playtest 92325 (#4121)

* style activity role tooltip like instruction inline tooltips

* style updates to activity details

* don't show token underlines in practice mode

* show loading activity analytics

* use all construct types to calculate activity analytics, include audio messages in activity summary request

* update chat context menus for activities

* fix positioning on menu in main chat list

* chore: update activity session notification to open activity start page without joining activity (#4122)

* chore: add copy to describe writing analytics (#4123)

* feat: new onboarding flow (#4112)

* feat: new onboarding flow

* go to course details page on click course template in setup page

* update route redirects

* style tweaks

* chore: add gold shimmer to active token practice buttons (#4131)

* chore: remove unnecessary spacing (#4132)

* fix: don't show end activity button until activity has started (#4134)

* chore: add no courses found indicator (#4135)

* chore: update course edit saving logic (#4136)

* chore: add loading indicator to course settings page (#4137)

* fix: use outer context when navigating via course chat popup (#4139)

* chore: update some copy in filter dropdowns (#4140)

* chore: make terms and conditions links work (#4141)

* chore: remove unnecessary padding (#4143)

* fix: hide activity role tooltip during translation (#4145)

* fix: always allow show menu on click activity participant (#4146)

* chore: remove text scaling in emoji mode (#4147)

* chore: increase size of user activity summary widgets (#4149)

* chore: make whole upper acitivty summary clickable to expand (#4150)

* fix: always set vocab as default tab in analytics page (#4151)

* build: fix lints for new flutter version (#4154)

* chore: changes to chat list main view (#4158)

* chore: changes to chat list main view

* remove onboarding page

* Make underlines translucent so lower parts of letters can be seen (#4160)

* 4142-allow-giving-of-activity-feedback (#4144)

* feat: activity feedback repo

* add UI for giving activity feedback

---------

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>
Co-authored-by: ggurdin <ggurdin@gmail.com>

* fix: don't dispose new word overlay animation early (#4168)

* 4152 onboarding tweaks (#4163)

* filter courses by short lang codes

* reduce padding in course details page

* update home / registration routes

* refactor: replace find your people page with new course page from onboarding

* chore: on course search, always load course IDs from server (#4174)

* fix: fix double analytics view in two column mode (#4175)

* feat: on create course, go to invite page while course creation loads (#4178)

* chore: give activity goal tooltip max width (#4179)

* chore: remove horizontal offset from pressable button widget (#4180)

* chore: in space analytics tab on small screens show language code in language dropdown (#4182)

* chore: in reading asssitance input bar, if all practice activities for message are completed, show all done message (#4183)

* 4181 japanese words grouped when should be separate (#4184)

* fix: only continue pickup up adjacent tokens while they are punctuation

* uncomment commented out code

* chore: when igc has matches, make send button color disabled instead of red (#4185)

* chore: don't show choreo error on timeout after canceling translation (#4189)

* consume image sizes from cms, surface course plan activity locations apis (#4187)

* 4152 onboarding tweaks (#4190)

* filter courses by short lang codes

* reduce padding in course details page

* update home / registration routes

* refactor: replace find your people page with new course page from onboarding

* chore: add redirect to onboarding course plan page if user not in course

* chore: re-style onboarding buttons (#4196)

* chore: match vocab lemma irrespective of case, use static message in activity stats dropdown (#4205)

* chore: show word card in click vocab word in activity summary (#4206)

* feat: integrate course translation group (#4209)

* integrate course translation group

* Update lib/pangea/payload_client/models/course_plan/cms_course_plan_translation_group.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* formatting

---------

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: ggurdin <ggurdin@gmail.com>

* chore: wait for user to send at least 3 text or audio messages before showing overlay with instructions about clicking activity status button

* fix: disable ping course participants button if there are no no-bot users in course to ping

* chore: show 'all done' message in practice activity bar for each activity type (#4212)

* Decrease unselected igc underline to 20% opacity (#4214)

* 4199 prevent activity menu tooltip from being interfered with my other overlays to ensure it always shows (#4215)

* don't show activity dropdown instructions if word card is open

* block other overlays from openning when tutorial overlay is open

* remove duplicate open overlay data, don't wait for construct banners to close if overlay fails to open

* chore: show selected archived activity, add tooltip to archived activity analytics view (#4217)

* feat: use cached space code to join space on create account (#4224)

* chore: hide course filters in onboarding pages (#4226)

* feat: show warning popup on l2/activity language mixup (#4229)

* chore: add some debugging statement for staging logout issue (#4234)

* fix: on SSO registration, pass langcode to onboarding pages (#4235)

* fix: refresh expired course cache (#4240)

* Adjust unread badge height to compensate for activity header height (#4213)

* Adjust unread badge height to compensate for activity header height

* Limit height instead of hardcoding values

* Hide course analytics download button on mobile (#4241)

* 4242 change course redirect (#4245)

* feat: connect with synapse public courses endpoint

* intergate course IDs into response model

* remove course redirect, update user's l2 on return to language selection page

* display on public courses page to go to page to make your own and display on make your on page to skip to rooms

* fix: hide activity finished status message for archived activities (#4246)

* fix: fix join with code redirect for non-spaces (#4248)

* 4172 color inconsistency of activity elements (#4247)

* activity menu color consistency

And some sizing changes, made the stats button box much smaller

* revert activity button size changes

Also make text bigger to fill box, and make menu/summary buttons solid colors so the shadow under the button works.

* feat: allow users to give token feedback in word card

* feat: set initial L2 via cached space code course target language if available (#4264)

* fix: fix onboarding redirect on login (#4265)

* Updating logo with Vector svg Image (#4263)

* Updated Logo with SVG image & adjusted margins to keep things center

* Un-formated the Index.html

* Remove invite option from participants widget in DM (#4256)

* chore: padding adjustment in selected course view (#4267)

* chore: on invite, also invite to course parent (#4268)

* fix: don't show language mismatch warning popup if activity lang matches L1 (#4269)

* fix: don't update profile until user controller initialized, redirect to rooms from SSO login, in create account page redirect to language selection page if no language available (#4274)

* feat: add selected course page for public courses, redirect there on click public course, filter out already-joined public courses (#4276)

* chore: remove l1 and CERF course filters from start course and public courses pages, update styling of l2 dropdown (#4278)

* integrate original course topic activity field (#4295)

* fix: fix start your own course link in public courses page (#4306)

* change seed to new vocab bubble (#4305)

* change seed to new vocab bubble

and tweak the animation to fade in, then rise/fade out since this looks better than spinning in.

* formatting

---------

Co-authored-by: ggurdin <ggurdin@gmail.com>

* Make users return to activity session when use invite back button (#4288)

* feat: add notification volume setting (#4310)

* chore: enable activity stats button if someone else finishes the activity (#4311)

* chore: on play with bot timeout, show warning popup (#4312)

* chore: show activity stats cutout tooltip on other user finish activity (#4316)

* 4307 bot in dms and activity chats only (#4319)

* remove bot settings files

* exclude bot in invite page

* listen to language / CERF level changes and update bot DM settings

* Update lib/pangea/common/controllers/pangea_controller.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: don't assume that list of IDs to fetch and list of fetched objects are the same length (#4322)

* chore: remove background color from activity goal tooltip (#4324)

* fix: prevent word card title from bouncing around (#4325)

* fix: on join activity with role, preload activity participants list to get accurate list of assigned roles (#4326)

* chore: give max width to activity participant indicator widgets (#4327)

* fix: add value key based on selected tab to course settings widget to force refresh on navigate from finished activity (#4331)

* fix: prevent overflows in token info feedback dialog on mobile, add more specific unsubscribed error in future loading dialog (#4333)

* fix: fix storage of selected language not working on mobile (#4334)

* chore: reduce padding around message in new trip page (#4335)

* chore: more specific error message on not found course with code (#4336)

* chore: dismiss last snackbar before show invite snackbar (#4337)

* chore: switch order of buttons in space delete dialog (#4338)

* chore: add custom map icons (#4339)

* chore: add create at and updated at fields to course plan model (#4340)

* chore: add leave space description (#4341)

* refactor: remove ability to directly edit lemma defintions and morph assignments (#4347)

* Organize course repos (#4262)

* integrate CoursePlansRepo.translateActivity, translateTopic, translateCoursePlan

* move translation functions to requisite files

* integrate translation endpoint

* refactor: reorganize course-related repos, add request and response model classes

* remove l2s from translation requests

* update translation request and response models, use translation endpoint to get course info, cache courses with L1s in cache key

* update topics repo to use translation endpoint

* use activity translation endpoint

* refactor: incremental loading of individual course info, account for discrepancy between translated IDs and original IDs

* incremental loading of course batches

* Update lib/pangea/course_plans/courses/course_plan_room_extension.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* cleanup

* cleanup

* fix: some name changes

* formatting

---------

Co-authored-by: WilsonLe <leanhminh2907@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: wcjord <32568597+wcjord@users.noreply.github.com>

* fix: use same context in show and hide token feedback snackbar to fix closing functionality (#4349)

* fix: filter courses only by short lang code (#4350)

* fix: filter courses only by short lang code

* Update lib/pangea/course_creation/course_search_provider.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update lib/pangea/login/pages/public_trip_page.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: always call setState on update target language filter

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Add select all button to the delete space dialog (#4353)

* Initial plan

* Add select all button to delete space dialog

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* Style select all button as CheckboxListTile

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* update copy

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>
Co-authored-by: ggurdin <ggurdin@gmail.com>

* 4354 room stuck indefinitely loading (#4357)

* fix: stop loading course if course plan provider if courseId is null

* don't allow padding of null string to loadCoursePlan

* fix: reload space course after updating course state event, wait for … (#4359)

* fix: reload space course after updating course state event, wait for course ID update in sync after returning from add course to space function

* Update lib/pangea/course_settings/course_settings.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: filter out public courses for which course ID failed to load (#4360)

* 3976 making emoji selection more of an activity (#4255)

* add shimmer in vocab page when no emoji selected

* fix shimmer in 2 column mode and add XP for first emoji selection

* add xp sparkle on emoji selection

* formatting, imports, widget name typo fix

* dont rebuild analytics page on every analytics stream update

* remove listener

* move animation and selection visual after slow function

for better visual flow and hopefully not noticeable stutter

* change transformTargetId into variable, update local display state before awaiting saving to analytics room

---------

Co-authored-by: ggurdin <ggurdin@gmail.com>

* Hide vocab analytics instructions when filtering or searching (#4362)

* Initial plan

* Hide instructions tooltip when searching or filtering vocabulary

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* Hide activity end prompt text when activity is archived (#4364)

* Initial plan

* Hide activity end prompt when activity is archived

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* fix: stop rebuilding whole course settings tab on screen size change (#4368)

* Fix foreground notification navigation to activity sessions for course pings (#4369)

* Initial plan

* Fix foreground notification navigation to activity sessions

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* Add clarifying comments to notification handling code

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* Refactor to reduce duplicate code between _onOpenNotification and goToRoom

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* chore: fix foreground notif small icon

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>
Co-authored-by: ggurdin <ggurdin@gmail.com>

* fix: show screen loading in course settings until activity roles are … (#4374)

* fix: show screen loading in course settings until activity roles are completly loaded

* show loading indicator over activity card on load course summary

* Update lib/pages/chat_details/chat_details.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: on load course topics, also load location media to get topic images (#4376)

* Add "Share course" tooltip to ShareRoomButton (#4375)

* Initial plan

* Add 'Share course' tooltip to ShareRoomButton

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* Move shareCourse localization to end of intl_en.arb

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* Remove L1 (base language) display from course info chips (#4378)

* Initial plan

* Remove L1 display from courses

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* chore: only show unlocalized language options in course search target language dropdowns (#4380)

* fix: after add course to existing space, push redirect route to refresh page (#4381)

* fix: update isActivityStarted to rely on assignedRoles instead of directly using state event (#4382)

* add XP animation on match activity tokens (#4373)

* 4379 show participants in public courses selection (#4383)

* chore: trip body / icons updates

* chore: display participant count in public courses page, update trip-related copy

* fix: add base language dropdown to language selection page on identic… (#4384)

* fix: add base language dropdown to language selection page on identical target and system language

* Update lib/pangea/login/utils/lang_code_repo.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: add cms api url to activity image paths to load properly (#4385)

* fix: don't mutate activity JSON image_url (#4386)

* Update onboarding language selection text to "Choose a target language" (#4393)

* Initial plan

* Update chooseLanguage text to "Choose a target language"

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* Update IT help message and remove unreferenced InstructionsEnum entries (#4391)

* Initial plan

* Update IT help message and remove unreferenced enum entries

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* Revert changes to non-English .arb files

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* remove unreferenced copy

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>
Co-authored-by: ggurdin <ggurdin@gmail.com>

* fix: alway hide back button in add course page (#4404)

* Move word card feedback notification from bottom to top of screen (#4402)

* Initial plan

* Replace bottom SnackBar with top overlay notification for word card feedback

Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>

* auto-close top token feedback snackbar after delay

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>
Co-authored-by: ggurdin <ggurdin@gmail.com>

* chore: add level bar / analytics to space details page on mobiel (#4405)

* chore: add skip button to add course page (#4407)

* chore: message on empty vocab filter (#4410)

* chore: add tooltip to describe vocab highlighting in activity dropdown menu (#4412)

* fix: don't delete archived activities on delete space (#4414)

* fix: don't delete archived activities on delete space

* use one list of futures in delete space function

* fix: refresh chat list on join with link (#4417)

* chore: make word card close and flag button the same styling and vertically aligned (#4419)

* fix: if a new user gets to account create page without target language in local storage or from course, direct them back to language selection (#4422)

* fix: handle room code on join with code (#4427)

* fix: push route on start to make add course page app bar back button work as expected (#4430)

* chore: update translations (#4188)

* translate more l1s

* Update translations for multiple languages (ar, bn, he, hi, id, ko, pt, ru, th, tr, zh)

* partial translations

* Add translations for Irish, Galician, Hungarian, Lithuanian, Slovenian, and Telugu

- Complete translations for 6 additional languages using OpenAI translation script
- Irish (ga): 1,612 translations added
- Galician (gl): 1,614 translations added
- Hungarian (hu): 1,615 translations added
- Lithuanian (lt): 1,927 translations added
- Slovenian (sl): 2,288 translations added
- Telugu (te): 2,388 translations added

These additions bring the total completed languages to 29 out of 47 (62% completion rate)

* Add translations for Estonian, Belarusian, and Greek

- Estonian (et): 164 translations added
- Belarusian (be): 2,392 translations added
- Greek (el): 2,342 translations added

These additions bring the total completed languages to 32 out of 47 (68% completion rate)

* Add Hebrew translations - Hebrew (he): 2,143 translations added - This brings the total completed languages to 33 out of 47 (70 percent completion rate)

* Add Arabic and Bengali translations - Arabic (ar): 1,692 translations added - Bengali (bn): 2,388 translations added - Total: 35 out of 47 languages complete (74 percent completion rate)

* Add Interlingua and Interlingue translations - Interlingua (ia): 2,378 translations added - Interlingue (ie): 2,149 translations added - Total: 37 out of 47 languages complete (79 percent completion rate)

* Add Georgian translations

* Add Esperanto translations

* Add Turkish translations

* Add Persian translations

* Add Romanian translations

* Improve translation script error handling

- Add JSON parsing error handling with retry logic
- Use simpler prompts on retry attempts
- Clean up markdown formatting from responses
- Skip failed chunks gracefully instead of crashing
- Successfully handle previously failing languages

* Update Georgian and add Romanian translations

* Add Serbian, Latvian, Slovak, Tamil and Basque translations

Successfully completed:
- Serbian (sr): 2062 translations
- Latvian (lv): 1614 translations
- Slovak (sk): 2158 translations
- Tamil (ta): 1696 translations
- Basque (eu): 1615 translations

Script improvements:
- Added metadata reconciliation error handling
- Successfully handles JSON parsing errors with retry logic

* fix needed translation generation script

* feat: translate missing keys for 49 languages and improve translation script

- Successfully translated 12,000+ keys across 49 languages (98% completion)
- Enhanced JSON error handling in translate script to recover from parsing errors
- Fixed metadata type issues for unreadChats placeholder in fil, pt_PT, and yue locales
- Added comprehensive run_all_translations.py script for batch translation
- Resolved duplicate yue locale conflicts
- Only Tibetan (bo) remains with 40 keys due to complex character encoding issues

Languages completed:
- Vietnamese, Portuguese (BR/PT), Romanian, Russian, Slovak, Slovenian
- Serbian, Swedish, Tamil, Telugu, Thai, Turkish, Ukrainian, Cantonese
- Chinese (Simplified/Traditional), and 34 other languages with 17 keys each

* fix not compilling error

* catch up with needed translations

* chore: on no courses found for language, log error (#4434)

* fix: fix scrolling in delete space dialog (#4436)

* build: bump version number

* chore: remove vocab tooltip from activity dropdown menu and update copy in end activity button (#4445)

* removed old code (#4446)

* change xp icon to star (#4431)

* fix: on login, don't open two separate databases (#4449)

* fix: register UIA listener on create login client, instead of on login (#4451)

* fix: on click space nav item use context.push to refresh course settings page (#4462)

* chore: add activity roles to activity summary request model (#4479)

* build: bump version number

---------

Co-authored-by: Kelrap <99418823+Kelrap@users.noreply.github.com>
Co-authored-by: Wilson <leanhminh2907@gmail.com>
Co-authored-by: avashilling <165050625+avashilling@users.noreply.github.com>
Co-authored-by: Brord van Wierst <brordvwierst@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: wcjord <32568597+wcjord@users.noreply.github.com>
Co-authored-by: Alexa "Tig" Harriss <alexa.harriss@gmail.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
ggurdin 2025-10-30 11:21:19 -04:00 committed by GitHub
parent 1c7166ca52
commit 044726fed5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
675 changed files with 665782 additions and 134684 deletions

3
.env
View file

@ -11,4 +11,5 @@ RC_OFFERING_NAME = 'test'
STRIPE_MANAGEMENT_LINK = 'https://billing.stripe.com/p/login/test_9AQaI8d3O9lmaXe5kk'
SUPPORT_SPACE_ID = '!gqSNSkvwTpgumyjLsV:staging.pangea.chat'
SUPPORT_SPACE_ID = '!gqSNSkvwTpgumyjLsV:staging.pangea.chat'
GOOGLE_API_KEY = 'AIzaSyD1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q'

View file

@ -1,6 +1,9 @@
# #Pangea
# name: Check duplicates
on:
# on:
# issues:
# types: [opened]

View file

@ -1,105 +1,101 @@
# #Pangea
# name: Pull Request Workflow
name: Pull Request Workflow
# on:
# pull_request:
# merge_group:
on:
pull_request:
merge_group:
# jobs:
# code_tests:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - run: ./scripts/generate-locale-config.sh
# - run: git diff --exit-code
# - run: cat .github/workflows/versions.env >> $GITHUB_ENV
# - uses: subosito/flutter-action@v2
# with:
# flutter-version: ${{ env.FLUTTER_VERSION }}
# cache: true
# - run: flutter pub get
# - run: flutter gen-l10n
# - name: Check formatting
# run: dart format lib/ test/ --set-exit-if-changed
# - name: Check import formatting
# run: dart run import_sorter:main --no-comments --exit-if-changed
# - name: Check license compliance
# run: dart run license_checker check-licenses -c licenses.yaml --problematic
# - run: flutter analyze
# - name: Apply google services patch
# run: git apply ./scripts/enable-android-google-services.patch
# - run: flutter analyze
# - run: flutter test
jobs:
code_tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- run: ./scripts/generate-locale-config.sh
- run: git diff --exit-code
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- run: flutter pub get
- run: flutter gen-l10n
- name: Check formatting
run: dart format lib/ test/ --set-exit-if-changed
- name: Check import formatting
run: dart run import_sorter:main --no-comments --exit-if-changed
- name: Check license compliance
run: dart run license_checker check-licenses -c licenses.yaml --problematic
- run: flutter analyze
- name: Add Firebase Messaging # Add android and analyze again
run: ./scripts/add-firebase-messaging.sh
- run: flutter analyze
- run: flutter test
# build_apk:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - run: cat .github/workflows/versions.env >> $GITHUB_ENV
# - uses: actions/setup-java@v4
# with:
# java-version: ${{ env.JAVA_VERSION }}
# distribution: "zulu"
# - uses: subosito/flutter-action@v2
# with:
# flutter-version: ${{ env.FLUTTER_VERSION }}
# cache: false
# - run: flutter pub get
# - name: Free Disk Space (Ubuntu)
# uses: jlumbroso/free-disk-space@main
# with:
# # this might remove tools that are actually needed,
# # if set to "true" but frees about 6 GB
# tool-cache: false
# android: false
# - run: flutter build apk --debug
build_debug_apk:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: "zulu"
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- uses: moonrepo/setup-rust@v1
- name: Add Firebase Messaging
run: ./scripts/add-firebase-messaging.sh
- run: flutter build apk --debug --target-platform android-arm # Pangea change, only build arm to decrease size & time
# build_web:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - run: cat .github/workflows/versions.env >> $GITHUB_ENV
# - uses: subosito/flutter-action@v2
# with:
# flutter-version: ${{ env.FLUTTER_VERSION }}
# cache: false
# - run: flutter pub get
# - name: Prepare web
# run: ./scripts/prepare-web.sh
# - run: flutter build web
build_debug_web:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- uses: moonrepo/setup-rust@v1
- run: rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
- run: flutter pub get
- name: Prepare web
run: ./scripts/prepare-web.sh
- run: flutter build web
# commented out because we do not build Pangea Chat to linux
# build_debug_linux:
# strategy:
# matrix:
# arch: [ x64, arm64 ]
# runs-on: ${{ matrix.arch == 'arm64' && 'self-hosted' || 'ubuntu-latest'}}
# steps:
# - uses: actions/checkout@v4
# - run: cat .github/workflows/versions.env >> $GITHUB_ENV
# - name: Install dependencies
# run: sudo apt-get update && sudo apt-get install git wget curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libssl-dev libwebkit2gtk-4.1-dev -y
# - name: Install Flutter
# run: |
# git clone --branch ${{ env.FLUTTER_VERSION }} https://github.com/flutter/flutter.git
# ./flutter/bin/flutter doctor
# - run: ./flutter/bin/flutter pub get
# - run: ./flutter/bin/flutter build linux --target-platform linux-${{ matrix.arch }}
build_debug_linux:
strategy:
matrix:
arch: [ arm64 ] # Pangea Disabled x64
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest'}}
steps:
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install git wget curl libcurl4-openssl-dev clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libssl-dev libwebkit2gtk-4.1-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev -y
- name: Install Flutter
run: |
git clone --branch ${{ env.FLUTTER_VERSION }} https://github.com/flutter/flutter.git
./flutter/bin/flutter doctor
- uses: moonrepo/setup-rust@v1
- run: ./flutter/bin/flutter pub get
- run: ./flutter/bin/flutter build linux --target-platform linux-${{ matrix.arch }}
# build_debug_ios:
# runs-on: macos-15
# steps:
# - uses: actions/checkout@v4
# - run: cat .github/workflows/versions.env >> $GITHUB_ENV
# - uses: subosito/flutter-action@v2
# with:
# flutter-version: ${{ env.FLUTTER_VERSION }}
# cache: true
# - name: Setup Xcode version
# uses: maxim-lobanov/setup-xcode@v1.6.0
# with:
# xcode-version: latest
# - run: brew install sqlcipher
# - run: flutter pub get
# - run: flutter build ipa --no-codesign
# Pangea#
build_debug_ios:
runs-on: macos-15
steps:
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Use Xcode 16.4
run: sudo xcode-select --switch /Applications/Xcode_16.4.app
- run: brew install sqlcipher
- uses: moonrepo/setup-rust@v1
- name: Add Firebase Messaging
run: ./scripts/add-firebase-messaging.sh
- run: flutter pub get
- run: flutter build ios --no-codesign

View file

@ -17,33 +17,3 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
NUMBER: ${{ github.event.issue.number }}
- name: Set project ID
run: |
echo "PROJECT_ID=PVT_kwDOBndSo84A7FWL" >> $GITHUB_ENV
- name: Get item ID for issue in project
id: get_item_id
run: |
ITEM_ID=$(gh api graphql -f query='query { repository(owner: "${{ github.repository_owner }}", name: "${{ github.event.repository.name }}") { issue(number: ${{ github.event.issue.number }}) { projectItems(first: 10) { nodes { id project { id } } } } }' --jq '.data.repository.issue.projectItems.nodes[] | select(.project.id==env.PROJECT_ID) | .id')
echo "ITEM_ID=$ITEM_ID" >> $GITHUB_ENV
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get status field and Done option IDs
id: get_status_ids
run: |
STATUS_FIELD_ID=$(gh api graphql -f query='query { node(id: "'$PROJECT_ID'") { ... on ProjectV2 { fields(first: 20) { nodes { id name } } } } }' --jq '.data.node.fields.nodes[] | select(.name=="Status") | .id')
DONE_OPTION_ID=$(gh api graphql -f query='query { node(id: "'$STATUS_FIELD_ID'") { ... on ProjectV2Field { options { id name } } } }' --jq '.data.node.options[] | select(.name=="Done") | .id')
echo "STATUS_FIELD_ID=$STATUS_FIELD_ID" >> $GITHUB_ENV
echo "DONE_OPTION_ID=$DONE_OPTION_ID" >> $GITHUB_ENV
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set status to Done in project
run: |
gh api graphql -f query='mutation($project:ID!, $item:ID!, $field:ID!, $option:ID!) { updateProjectV2ItemFieldValue(input: {projectId: $project, itemId: $item, fieldId: $field, value: { singleSelectOptionId: $option } }) { projectV2Item { id } } }' -f project=$PROJECT_ID -f item=$ITEM_ID -f field=$STATUS_FIELD_ID -f option=$DONE_OPTION_ID
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PROJECT_ID: ${{ env.PROJECT_ID }}
ITEM_ID: ${{ env.ITEM_ID }}
STATUS_FIELD_ID: ${{ env.STATUS_FIELD_ID }}
DONE_OPTION_ID: ${{ env.DONE_OPTION_ID }}
# To get your project, field, and option IDs, see the instructions in the new issue_opened_project.yaml file.
# You must replace the placeholders with your actual project and field IDs.

View file

@ -20,11 +20,18 @@ jobs:
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
- run: flutter pub get
- uses: moonrepo/setup-rust@v1
- run: rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
- name: Prepare web
run: ./scripts/prepare-web.sh
- run: rm ./assets/vodozemac/.gitignore
- run: flutter pub get
- name: Build Release Web
run: ./scripts/build-web.sh
run: |
flutter config --enable-web
flutter clean
flutter pub get
flutter build web --dart-define=FLUTTER_WEB_CANVASKIT_URL=canvaskit/ --profile --source-maps
- name: Upload files
uses: actions/upload-artifact@v4

View file

@ -28,7 +28,6 @@ jobs:
- uses: actions/setup-java@v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: 'zulu'
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
@ -40,6 +39,9 @@ jobs:
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
distribution: 'zulu'
- name: Add Firebase Messaging
run: ./scripts/add-firebase-messaging.sh
- name: Update env files to selected environment
run: |
rm .env

View file

@ -48,6 +48,8 @@ jobs:
cache: true
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install nodejs -y
- uses: moonrepo/setup-rust@v1
- run: rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
- run: flutter pub get
- name: Prepare web
run: ./scripts/prepare-web.sh
@ -58,11 +60,7 @@ jobs:
echo "$WEB_APP_ENV" > .env
echo "$WEB_APP_ENV" > assets/.env
- name: Build Release Web
run: |
flutter config --enable-web
flutter clean
flutter pub get
flutter build web --dart-define=FLUTTER_WEB_CANVASKIT_URL=canvaskit/ --release --source-maps
run: flutter build web --dart-define=FLUTTER_WEB_CANVASKIT_URL=canvaskit/ --release --source-maps --base-href "/web/"
- name: Create archive
run: tar -czf pangeachat-web.tar.gz build/web/
- name: Upload Web Build
@ -102,6 +100,8 @@ jobs:
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
- name: Add Firebase Messaging
run: ./scripts/add-firebase-messaging.sh
- name: Set up Android SDK
if: ${{ env.ACT }} # Only run on local act setups, as GitHub Actions provides the Android SDK on Ubuntu
uses: android-actions/setup-android@v2
@ -117,12 +117,11 @@ jobs:
cp .env assets/.env
- name: Apply .env patch
run: git apply ./scripts/enable_mobile_env.patch
- name: Install Fastlane
run: gem install fastlane -NV
- name: Remove Emoji Font
run: |
rm -rf fonts/NotoEmoji
yq -i 'del( .flutter.fonts[] | select(.family == "NotoEmoji") )' pubspec.yaml
- uses: moonrepo/setup-rust@v1
- run: flutter pub get
- name: Prepare Android Release Build
env:
@ -143,38 +142,35 @@ jobs:
asset_name: pangeachat.apk
asset_content_type: application/vnd.android.package-archive
# #Pangea
# build_linux:
# strategy:
# matrix:
# arch: [ x64 ]
# runs-on: ubuntu-latest
# needs: create_release
# steps:
# - uses: actions/checkout@v4
# - run: cat .github/workflows/versions.env >> $GITHUB_ENV
# - name: Install dependencies
# run: sudo apt-get update && sudo apt-get install curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libssl-dev libwebkit2gtk-4.1-dev -y
# - name: Install dependencies for audio-player
# run: sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
# - name: Install Flutter
# run: |
# git clone --branch ${{ env.FLUTTER_VERSION }} https://github.com/flutter/flutter.git
# ./flutter/bin/flutter doctor
# - run: ./flutter/bin/flutter pub get
# - run: ./flutter/bin/flutter build linux --target-platform linux-${{ matrix.arch }}
# - name: Create archive
# run: tar -czf pangeachat-linux-${{ matrix.arch }}.tar.gz -C build/linux/${{ matrix.arch }}/release/bundle/ .
# - name: Upload to release
# uses: actions/upload-release-asset@v1
# env:
# GITHUB_TOKEN: ${{ secrets.PAGES_DEPLOY_TOKEN }}
# with:
# upload_url: ${{ needs.create_release.outputs.upload_url }}
# asset_path: pangeachat-linux-${{ matrix.arch }}.tar.gz
# asset_name: pangeachat-linux-${{ matrix.arch }}.tar.gz
# asset_content_type: application/gzip
# Pangea#
build_linux:
strategy:
matrix:
arch: [ x64 ]
runs-on: ubuntu-latest
needs: create_release
steps:
- uses: actions/checkout@v5
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libssl-dev libwebkit2gtk-4.1-dev -y
- name: Install Flutter
run: |
git clone --branch ${{ env.FLUTTER_VERSION }} https://github.com/flutter/flutter.git
./flutter/bin/flutter doctor
- uses: moonrepo/setup-rust@v1
- run: ./flutter/bin/flutter pub get
- run: ./flutter/bin/flutter build linux --target-platform linux-${{ matrix.arch }}
- name: Create archive
run: tar -czf fluffychat-linux-${{ matrix.arch }}.tar.gz -C build/linux/${{ matrix.arch }}/release/bundle/ .
- name: Upload to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.PAGES_DEPLOY_TOKEN }}
with:
upload_url: ${{ needs.create_release.outputs.upload_url }}
asset_path: pangeachat-linux-${{ matrix.arch }}.tar.gz
asset_name: pangeachat-linux-${{ matrix.arch }}.tar.gz
asset_content_type: application/gzip
deploy_web:
runs-on: ubuntu-latest
@ -201,4 +197,4 @@ jobs:
aws s3 sync ./build/web s3://$WEBAPP_S3_BUCKET
- name: AWS CloudFront Invalidation
run: |
aws cloudfront create-invalidation --distribution-id $CF_DISTRIBUTION_ID --paths "/*"
aws cloudfront create-invalidation --distribution-id $CF_DISTRIBUTION_ID --paths "/*"

View file

@ -1,2 +1,2 @@
FLUTTER_VERSION=3.32.1
FLUTTER_VERSION=3.35.3
JAVA_VERSION=17

1546
.gitignore vendored

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,24 @@
## v2.0.0
This version migrates to Vodozemac and Matrix Dart SDK 1.0.0. This is a breaking
change. The user should not notice the migration at all but downgrading from
v2.0.0 to a previous version is not possible without losing the session.
- fix: Do not set read markers for sending events (Christian Kußowski)
- fix: fix compile error related to MxcImage (gilice)
- fix: Forward last version of events when forwarding (Christian Kußowski)
- fix: Ban button displayed for already banned users (Christian Kußowski)
- fix: Route back to room list after leaving a chat (Christian Kußowski)
- build: Switch to matrix sdk 1.0.0 (Christian Kußowski)
- build: Upgrade flutter to 3.32.2 (krille-chan)
- build: Update to flutter 3.32.4 (Christian Kußowski)
- chore: Add missing mounted check (Christian Kußowski)
- chore: highlight select mode actions (Christian Kußowski)
- refactor: sdk 1.0 (Christian Kußowski)
- refactor: New message context menu (Christian Kußowski)
- refactor: Nicer popupmenus (Christian Kußowski)
- Translated using Weblate (Spanish) (Kimby)
## v1.27.0
- feat: Add confirmation dialog before accepting invite (krille-chan)
- feat: Add feature flag for refresh tokens (Christian Kußowski)

View file

@ -1,5 +1,5 @@
FROM ghcr.io/cirruslabs/flutter as builder
RUN sudo apt update && sudo apt install curl wget jq -y
RUN sudo apt update && sudo apt install curl wget jq build-essential -y
WORKDIR /tmp
RUN wget https://github.com/mikefarah/yq/releases/download/v4.40.5/yq_linux_amd64.tar.gz
@ -8,6 +8,9 @@ RUN mv yq_linux_amd64 /usr/bin/yq
COPY . /app
WORKDIR /app
RUN curl https://sh.rustup.rs -sSf | bash -s -- -y
ENV PATH="/root/.cargo/bin:${PATH}"
RUN rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
RUN ./scripts/prepare-web.sh
COPY config.* /app/
RUN flutter pub get

View file

@ -25,7 +25,7 @@
* To run on Android:
* Download Android File Transfer here: https://www.android.com/filetransfer/
* To run the app from VSCode terminal:
* On web, run `flutter run -d chrome hot`
* On web, run `flutter run -d chrome --hot`
* Or as a web server (Usage with WSL or remote connect) `flutter run --release -d web-server -web-port=3000`
* On mobile device or simulator, run `flutter run hot -d <DEVICE_NAME>`

View file

@ -1,112 +0,0 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
//id "com.google.gms.google-services"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
compileSdk = 35
namespace = "com.talktolearn.chat"
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// #Pangea
// applicationId "chat.fluffy.fluffychat"
applicationId "com.talktolearn.chat"
// Pangea#
minSdkVersion 21
targetSdkVersion 35
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
signingConfigs {
release {
if (keystorePropertiesFile.exists()) {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
versionNameSuffix "-debug"
}
release {
minifyEnabled false
shrinkResources false
signingConfig signingConfigs.release
}
}
// https://stackoverflow.com/a/77494454/8222484
packagingOptions {
pickFirst 'lib/x86/libc++_shared.so'
pickFirst 'lib/x86_64/libc++_shared.so'
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
pickFirst 'lib/arm64-v8a/libc++_shared.so'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
coreLibraryDesugaringEnabled true
}
kotlinOptions {
jvmTarget = "17"
}
}
flutter {
source '../..'
}
dependencies {
//implementation 'com.google.firebase:firebase-messaging:19.0.1' // Workaround for https://github.com/microg/android_packages_apps_GmsCore/issues/313#issuecomment-617651698
implementation 'androidx.multidex:multidex:2.0.1'
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
}
// #Pangea
// configurations.all {
// exclude group: 'com.google.android.gms'
// }
// Pangea#

View file

@ -0,0 +1,104 @@
import java.util.Properties
import java.io.FileInputStream
plugins {
id("com.android.application")
id("kotlin-android")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}
// conditionally apply google-services (keeps your original intent)
if (file("google-services.json").exists()) {
apply(plugin = "com.google.gms.google-services")
}
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4") // For flutter_local_notifications // Workaround for: https://github.com/MaikuB/flutter_local_notifications/issues/2286
implementation(platform("com.google.firebase:firebase-bom:32.8.0"))
implementation("com.google.firebase:firebase-analytics")
implementation("com.google.firebase:firebase-database")
implementation("androidx.multidex:multidex:2.0.1")
}
// Workaround for https://pub.dev/packages/unifiedpush#the-build-fails-because-of-duplicate-classes
configurations.all {
// Use the latest version published: https://central.sonatype.com/artifact/com.google.crypto.tink/tink-android
val tink = "com.google.crypto.tink:tink-android:1.17.0"
// You can also use the library declaration catalog
// val tink = libs.google.tink
resolutionStrategy {
force(tink)
dependencySubstitution {
substitute(module("com.google.crypto.tink:tink")).using(module(tink))
}
}
}
android {
namespace = "com.talktolearn.chat"
compileSdk = 35
// compileSdk = flutter.compileSdkVersion
// ndkVersion = "27.0.12077973"
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
isCoreLibraryDesugaringEnabled = true
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
}
signingConfigs {
create("release") {
keyAlias = "dummyAlias"
keyPassword = "dummyPassword"
storeFile = file("dummy.keystore")
storePassword = "dummyStorePassword"
}
}
val keystoreProperties = Properties()
val keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
signingConfigs.getByName("release").apply {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
storeFile = keystoreProperties["storeFile"]?.let { file(it) }
storePassword = keystoreProperties["storePassword"] as String
}
}
defaultConfig {
applicationId = "com.talktolearn.chat"
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
debug {
signingConfig = signingConfigs.getByName("debug")
versionNameSuffix = "-debug"
isMinifyEnabled = false
isShrinkResources = false
}
release {
isMinifyEnabled = false
isShrinkResources = false
// use the release signing config we created above (will be used only if key properties exist)
signingConfig = signingConfigs.getByName("release")
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}
}
}
flutter {
source = "../.."
}

View file

@ -1,8 +1,9 @@
{
"project_info": {
"project_number": "545984292675",
"firebase_url": "https://pangea-chat-936ee-default-rtdb.firebaseio.com",
"project_id": "pangea-chat-936ee",
"storage_bucket": "pangea-chat-936ee.appspot.com"
"storage_bucket": "pangea-chat-936ee.firebasestorage.app"
},
"client": [
{

View file

@ -42,7 +42,7 @@
>
<activity
android:name=".MainActivity"
android:launchMode="singleInstance"
android:launchMode="singleTask"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
@ -108,6 +108,19 @@
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="pangea" />
<data android:host="app.pangea.chat" />
</intent-filter>
<meta-data
android:name="flutter_deeplinking_enabled"
android:value="true" />
</activity>
<activity

View file

@ -2,17 +2,9 @@
import com.famedly.fcm_shared_isolate.FcmSharedIsolateService
import com.talktolearn.chat.MainActivity
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.view.FlutterMain
import io.flutter.embedding.engine.dart.DartExecutor.DartEntrypoint
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.WindowManager
class FcmPushService : FcmSharedIsolateService() {
override fun getEngine(): FlutterEngine {

View file

@ -4,13 +4,11 @@ import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import android.content.Context
import androidx.multidex.MultiDex
class MainActivity : FlutterActivity() {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(this)
}
@ -30,4 +28,4 @@ class MainActivity : FlutterActivity() {
return eng
}
}
}
}

View file

@ -1,23 +0,0 @@
package com.talktolearn.chat
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.dart.DartExecutor
import org.unifiedpush.flutter.connector.UnifiedPushReceiver
import android.content.Context
class UnifiedPushReceiver : UnifiedPushReceiver() {
override fun getEngine(context: Context): FlutterEngine {
var engine = MainActivity.engine
if (engine == null) {
engine = MainActivity.provideEngine(context)
engine.localizationPlugin.sendLocalesToFlutter(
context.resources.configuration
)
engine.dartExecutor.executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
)
}
return engine
}
}

View file

@ -1,17 +0,0 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
project.evaluationDependsOn(":app")
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

31
android/build.gradle.kts Normal file
View file

@ -0,0 +1,31 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get()
rootProject.layout.buildDirectory.value(newBuildDir)
subprojects {
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
project.layout.buildDirectory.value(newSubprojectBuildDir)
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register<Delete>("clean") {
delete(rootProject.layout.buildDirectory)
}
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.google.gms:google-services:4.4.1")
}
}

View file

@ -1,38 +0,0 @@
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
buildscript {
repositories {
mavenCentral()
maven {
url = uri("https://storage.googleapis.com/r8-releases/raw")
}
}
dependencies {
classpath("com.android.tools:r8:8.2.24")
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.7.3" apply false
id "org.jetbrains.kotlin.android" version "2.1.10" apply false
// id "com.google.gms.google-services" version "4.3.8" apply false
}
include ":app"

View file

@ -0,0 +1,40 @@
pluginManagement {
val flutterSdkPath = run {
val properties = java.util.Properties()
file("local.properties").inputStream().use { properties.load(it) }
val flutterSdkPath = properties.getProperty("flutter.sdk")
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
flutterSdkPath
}
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
buildscript {
repositories {
mavenCentral()
maven {
url = uri("https://storage.googleapis.com/r8-releases/raw")
}
}
dependencies {
classpath("com.android.tools:r8:8.2.24")
}
}
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.7.3" apply false
id("org.jetbrains.kotlin.android") version "2.1.10" apply false
if (file("app/google-services.json").exists()) {
id("com.google.gms.google-services") version "4.3.8" apply false
}
}
include(":app")

3
assets/pangea/check.svg Normal file
View file

@ -0,0 +1,3 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23.7203 42.6667L5.81818 26.6667L0 32L23.2727 64L64 5.33333V0L23.7203 42.6667Z" fill="#03A514"/>
</svg>

After

Width:  |  Height:  |  Size: 209 B

1
assets/vodozemac/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
vodozemac_bindings_dart*

View file

@ -46,7 +46,12 @@
target="_blank" class="text-xl underline hover:text-purple-800 dark:hover:text-purple-400">matrix</a>]
</p>
<img src="screenshots/screenshots.png" alt="Mobile and desktop screenshots" class="max-w-xl mb-16 w-full px-8" />
<div class="flex flex-wrap justify-center mb-16 w-full px-8 gap-4">
<img src="screenshots/mobile.png" alt="Mobile screenshot"
class="h-96 w-auto object-contain rounded-xl border border-gray-300 shadow-xl" />
<img src="screenshots/desktop.png" alt="Desktop screenshot"
class="h-96 w-auto object-contain rounded-xl border border-gray-300 shadow-xl" />
</div>
<div class="max-w-lg mb-16 flex justify-center flex-wrap">
<a href="https://apps.apple.com/app/fluffychat/id1551469600"><img src="appstore-badge.png"

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 556 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 518 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 370 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 KiB

View file

@ -1,3 +1,8 @@
source "https://rubygems.org"
gem "fastlane"
# Workaround for ruby 3.4 https://github.com/fastlane/fastlane/issues/29183
gem "abbrev"
gem "mutex_m"
gem "ostruct"

View file

@ -28,6 +28,14 @@
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>pangea</string>
</array>
<key>CFBundleURLName</key>
<string>com.talktolearn.chat</string>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
@ -113,5 +121,7 @@
<false/>
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>FlutterDeepLinkingEnabled</key>
<true/>
</dict>
</plist>

View file

@ -1,18 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:example.com</string>
</array>
<key>com.apple.security.application-groups</key>
<!-- #Pangea -->
<array>
<string>group.com.talktolearn.chat</string>
</array>
<!-- Pangea# -->
</dict>
</plist>
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:app.pangea.chat</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.talktolearn.chat</string>
</array>
</dict>
</plist>

View file

@ -27,9 +27,10 @@ abstract class AppConfig {
static const bool allowOtherHomeservers = true;
static const bool enableRegistration = true;
// #Pangea
static const double toolbarMaxHeight = 250.0;
static const double toolbarMaxHeight = 225.0;
static const double toolbarMinHeight = 150.0;
static const double toolbarMinWidth = 350.0;
static const double toolbarMenuHeight = 50.0;
static const double defaultHeaderHeight = 56.0;
static const double toolbarButtonsHeight = 50.0;
static const double toolbarSpacing = 8.0;
@ -89,6 +90,8 @@ abstract class AppConfig {
static String _privacyUrl = "https://www.pangeachat.com/privacy";
//Pangea#
static const Set<String> defaultReactions = {'👍', '❤️', '😂', '😮', '😢'};
static String get privacyUrl => _privacyUrl;
// #Pangea
// static const String website = 'https://fluffychat.im';
@ -191,6 +194,8 @@ abstract class AppConfig {
"https://pangea-chat-client-assets.s3.us-east-1.amazonaws.com";
static String errorSubscriptionId = "pangea_subscription_error";
static double volume = 1.0;
// Pangea#
static void loadFromJson(Map<String, dynamic> json) {

View file

@ -52,7 +52,7 @@ class DefaultFirebaseOptions {
projectId: 'pangea-chat-936ee',
authDomain: 'pangea-chat-936ee.firebaseapp.com',
databaseURL: 'https://pangea-chat-936ee-default-rtdb.firebaseio.com',
storageBucket: 'pangea-chat-936ee.appspot.com',
storageBucket: 'pangea-chat-936ee.firebasestorage.com',
measurementId: 'G-FKP13VDEBX',
);
@ -62,7 +62,7 @@ class DefaultFirebaseOptions {
messagingSenderId: '545984292675',
projectId: 'pangea-chat-936ee',
databaseURL: 'https://pangea-chat-936ee-default-rtdb.firebaseio.com',
storageBucket: 'pangea-chat-936ee.appspot.com',
storageBucket: 'pangea-chat-936ee.firebasestorage.com',
androidClientId:
'545984292675-2amsnoan1mt6lec1fld1a7eagu6gej7o.apps.googleusercontent.com',
);
@ -73,7 +73,7 @@ class DefaultFirebaseOptions {
messagingSenderId: '545984292675',
projectId: 'pangea-chat-936ee',
databaseURL: 'https://pangea-chat-936ee-default-rtdb.firebaseio.com',
storageBucket: 'pangea-chat-936ee.appspot.com',
storageBucket: 'pangea-chat-936ee.firebasestorage.com',
iosClientId:
'545984292675-f5p76l3h9sibsonrct7a8l9ca3c69at0.apps.googleusercontent.com',
iosBundleId: 'com.talktolearn.chat',
@ -85,7 +85,7 @@ class DefaultFirebaseOptions {
messagingSenderId: '545984292675',
projectId: 'pangea-chat-936ee',
databaseURL: 'https://pangea-chat-936ee-default-rtdb.firebaseio.com',
storageBucket: 'pangea-chat-936ee.appspot.com',
storageBucket: 'pangea-chat-936ee.firebasestorage.com',
iosClientId:
'545984292675-f5p76l3h9sibsonrct7a8l9ca3c69at0.apps.googleusercontent.com',
iosBundleId: 'com.talktolearn.chat',

File diff suppressed because it is too large Load diff

View file

@ -34,6 +34,9 @@ abstract class SettingKeys {
static const String showPresences = 'chat.fluffy.show_presences';
static const String displayNavigationRail =
'chat.fluffy.display_navigation_rail';
// #Pangea
static const String volume = 'pangea.volume';
// Pangea#
}
enum AppSettings<T> {
@ -53,10 +56,12 @@ enum AppSettings<T> {
'https://sygnal.pangea.chat/_matrix/push/v1/notify',
// Pangea#
),
pushNotificationsPusherFormat<String>(
'pushNotificationsPusherFormat',
'event_id_only',
),
// #Pangea
// pushNotificationsPusherFormat<String>(
// 'pushNotificationsPusherFormat',
// 'event_id_only',
// ),
// Pangea#
shareKeysWith<String>('chat.fluffy.share_keys_with_2', 'all'),
noEncryptionWarningShown<bool>(
'chat.fluffy.no_encryption_warning_shown',

View file

@ -7,6 +7,8 @@ import 'app_config.dart';
abstract class FluffyThemes {
static const double columnWidth = 380.0;
static const double maxTimelineWidth = columnWidth * 2;
// #Pangea
// static const double navRailWidth = 80.0;
static const double navRailWidth = 72.0;
@ -63,8 +65,11 @@ abstract class FluffyThemes {
? colorScheme.surfaceContainerHighest
: colorScheme.surfaceContainer,
popupMenuTheme: PopupMenuThemeData(
color: colorScheme.surfaceContainerLow,
iconColor: colorScheme.onSurface,
textStyle: TextStyle(color: colorScheme.onSurface),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2),
),
),
segmentedButtonTheme: SegmentedButtonThemeData(
@ -95,8 +100,12 @@ abstract class FluffyThemes {
toolbarHeight: isColumnMode ? 72 : 56,
shadowColor:
isColumnMode ? colorScheme.surfaceContainer.withAlpha(128) : null,
surfaceTintColor: isColumnMode ? colorScheme.surface : null,
backgroundColor: isColumnMode ? colorScheme.surface : null,
// #Pangea
// surfaceTintColor: isColumnMode ? colorScheme.surface : null,
// backgroundColor: isColumnMode ? colorScheme.surface : null,
surfaceTintColor: colorScheme.surface,
backgroundColor: colorScheme.surface,
// Pangea#
systemOverlayStyle: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: brightness.reversed,

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -3240,6 +3240,7 @@
"commandHint_logout": "Logout your current device",
"commandHint_logoutall": "Logout all active devices",
"displayNavigationRail": "Show navigation rail on mobile",
"customReaction": "Custom reaction",
"accountInformation": "Account information",
"addGroupDescription": "Add a chat description",
"addNewFriend": "Add new friend",
@ -3268,8 +3269,6 @@
"greenFeedback": "That's what I would put!",
"yellowFeedback": "Hm, you can try that and see if it works! To use this word, just click it again.",
"redFeedback": "I don't think that's right...",
"itInstructionsTitle": "I can help you translate!",
"itInstructionsBody": "You can click and hold choices for word info.",
"oneday": "Last 24 hours",
"oneweek": "Last 7 days",
"onemonth": "Past month",
@ -3282,18 +3281,15 @@
"interactiveTranslatorAllowed": "Student Choice",
"interactiveTranslatorRequired": "Required",
"notYetSet": "Not yet set",
"multiLingualSpace": "Multilingual Space",
"myLearning": "My Analytics",
"waTooltip": "L2 use without assistance",
"changeDateRange": "Change date range",
"classDescription": "Description",
"addStudents": "Invite users by link or code",
"copyClassLink": "Copy invite link",
"copyClassLinkDesc": "Clicking this link will take users to the app, direct them to make an account and they will automatically join this space.",
"copyClassCode": "Copy invite code",
"inviteStudentByUserName": "Invite users by username",
"languageSettings": "Language Settings",
"languageSettingsDesc": "Edit space languages and proficiency level.",
"interactiveTranslator": "Translation assistance",
"shareVideo": "Share Video",
"shareVideoDesc": "Toggle this on to allow students to share videos in chats.",
@ -3307,9 +3303,8 @@
"iWantAConversationPartner": "I want a conversation partner who",
"iWantALanguagePartnerWhoSpeaks": "Speaks:",
"iWantALanguagePartnerWhoIsLearning": "Is learning:",
"joinWithClassCode": "Join space",
"joinWithClassCode": "Join course",
"joinWithClassCodeHint": "Enter invite code",
"unableToFindClass": "There's no space with that code. Please try again.",
"languageLevelPreA1": "True Beginner (Pre A1)",
"languageLevelA1": "Beginner (A1)",
"languageLevelA2": "Elementary (A2)",
@ -3358,9 +3353,8 @@
"errorDisableITUserDesc": "Click here to update translation assistance settings",
"errorDisableIGCUserDesc": "Click here to update grammar assistance settings",
"errorDisableLanguageAssistanceUserDesc": "Click here to update translation assistance and grammar assistance settings",
"errorDisableITClassDesc": "Translation assistance is turned off for the space that this chat is in.",
"errorDisableIGCClassDesc": "Grammar assistance is turned off for the space that this chat is in.",
"errorDisableLanguageAssistanceClassDesc": "Translation assistance and grammar assistance are turned off for the space that this chat is in.",
"errorDisableITClassDesc": "Translation assistance is turned off for the course that this chat is in.",
"errorDisableIGCClassDesc": "Grammar assistance is turned off for the course that this chat is in.",
"itIsDisabled": "Interactive Translation is disabled",
"igcIsDisabled": "Interactive Grammar Checking is disabled",
"goToLearningSettings": "Go to Learning Settings",
@ -3375,19 +3369,17 @@
"error404Title": "Translation error!",
"error404Desc": "Pangea Bot isn't sure how to translate that...",
"errorPleaseRefresh": "We're looking into it! Please reload and try again.",
"findAClass": "Find a class (coming soon)",
"toggleIT": "Interactive Translation",
"toggleIGC": "Interactive Grammar Checking",
"toggleToolSettingsDescription": "Here you can toggle your individual language tool settings.",
"connectedToStaging": "Connected to Staging",
"learningSettings": "Learning settings",
"classNameRequired": "Please enter a space name",
"sendVoiceNotes": "Send Voice Notes",
"sendVoiceNotesDesc": "Toggle this on to allow students to send voice notes in chats.",
"chatTopic": "Chat topic",
"chatTopicDesc": "Set a chat topic",
"inviteStudentByUserNameDesc": "If your student already has an account, you can search for them.",
"classRoster": "Participants",
"participants": "Participants",
"almostPerfect": "That seems right! Here's what I would have said.",
"prettyGood": "Pretty good! Here's what I would have said.",
"letMeThink": "Hmm, let's see how you did!",
@ -3437,9 +3429,6 @@
"toggleImmersionModeDesc": "When enabled, all messages are displayed in your target language. This setting is most useful in language exchanges.",
"itToggleDescription": "This language learning tool will identify words in your base language and help you translate them to your target language. Though rare, the AI can make translation errors.",
"igcToggleDescription": "This language learning tool will identify common spelling, grammar and punctuation errors in your message and suggest corrections. Though rare, the AI can make correction errors.",
"sendOnEnterDescription": "Turn this off to be able to add line spaces in messages. When the toggle is off on the browser app, you can press Shift + Enter to start a new line. When the toggle is off on mobile apps, just Enter will start a new line.",
"alreadyInClass": "You are already in this space.",
"pleaseLoginFirst": "Please login or sign up first and then you will be added to your space.",
"originalMessage": "Original Message",
"sentMessage": "Sent Message",
"useType": "Use Type",
@ -3450,12 +3439,10 @@
"definitionsToolDescription": "When enabled, words underlined in blue can be clicked for definitions. Click messages to access definitions.",
"translationsToolDescrption": "When enabled, click a message and the translation icon to see a message in your base language.",
"welcomeBack": "Welcome back! If you were part of the 2023-2024 pilot, please contact us for your special pilot subscription. If you are a teacher who has (or whose institution has) purchased licenses for your class, contact us for your teacher subscription.",
"createNewClass": "New class space",
"kickAllStudents": "Kick All Students",
"kickAllStudentsConfirmation": "Are you sure you want to kick all students?",
"inviteAllStudents": "Invite All Students",
"inviteAllStudentsConfirmation": "Are you sure you want to invite all students?",
"inviteStudentsFromOtherClasses": "Invite students from other spaces",
"inviteUsersFromPangea": "Add admins",
"redeemPromoCode": "Redeem Promo Code",
"enterPromoCode": "Enter Promo Code",
@ -3471,7 +3458,6 @@
}
},
"oneWeekTrial": "One Week Trial",
"creatingSpacePleaseWait": "Creating space. Please wait...",
"downloadXLSXFile": "Download Excel File",
"abDisplayName": "Abkhaz",
"aaDisplayName": "Afar",
@ -3916,9 +3902,7 @@
"pay": "Pay",
"allPrivateChats": "Direct chats",
"unknownPrivateChat": "Unknown private chat",
"copyClassCodeDesc": "Users who are already in the app can 'Join space' via the main menu.",
"addToSpaceDesc": "Adding a chat to a space will make the chat appear within the space for students and give them access.",
"invitedToSpace": "{user} has invited you to join a space: {space}! Do you wish to accept?",
"invitedToSpace": "{user} has invited you to join a course: {space}! Do you wish to accept?",
"@invitedToSpace": {
"placeholders": {
"space": {
@ -3932,30 +3916,6 @@
"declinedInvitation": "Declined invitation",
"acceptedInvitation": "Accepted invitation",
"youreInvited": "📩 You're invited!",
"studentPermissionsDesc": "Set permissions for this space. They will only apply to the space. They will override individual user settings.",
"noEligibleSpaces": "There are no eligible spaces to add this to.",
"youAddedToSpace": "You added {child} to {space}",
"@youAddedToSpace": {
"placeholders": {
"child": {
"type": "String"
},
"space": {
"type": "String"
}
}
},
"youRemovedFromSpace": "You removed {child} from {space}",
"@youRemovedFromSpace": {
"placeholders": {
"child": {
"type": "String"
},
"space": {
"type": "String"
}
}
},
"invitedToChat": "{user} has invited you to join a chat: {name}! Do you wish to accept?",
"@invitedToChat": {
"placeholders": {
@ -3983,10 +3943,6 @@
}
},
"emptyChatNameWarning": "Please enter a name for this chat",
"emptyClassNameWarning": "Please enter a name for this class",
"emptySpaceNameWarning": "Please enter a name for this space",
"blurMeansTranslateTitle": "Why is the message blurred?",
"blurMeansTranslateBody": "While Immersion Mode is on, messages that are sent in your base language will be blurred while Pangea Bot translates them to your target language. Immersion Mode can be toggled in individual and space settings.",
"someErrorTitle": "Hm, something's not right",
"someErrorBody": "It could be an error or something in your base language.",
"bestCorrectionFeedback": "That's correct!",
@ -3996,11 +3952,8 @@
"practiceDefaultPrompt": "What is the best answer?",
"correctionDefaultPrompt": "What is the best replacement?",
"itStartDefaultPrompt": "Do you want help translating?",
"languageLevelWarning": "Please select a space language level",
"lockedChatWarning": "🔒 This chat has been locked",
"lockSpace": "Lock Space",
"lockChat": "Lock Chat",
"archiveSpace": "Archive Space",
"suggestToChat": "Suggest this chat",
"suggestToChatDesc": "Suggested chats will appear in chat lists",
"acceptSelection": "Accept Correction",
@ -4036,7 +3989,6 @@
}
},
"noTeachersFound": "No teachers found to report to",
"createClass": "Create class",
"viewArchive": "View Archive",
"trialExpiration": "Your free trial expires on {expiration}",
"@trialExpiration": {
@ -4048,10 +4000,8 @@
},
"freeTrialDesc": "New users recieve a one week free trial of Pangea Chat",
"activateTrial": "Free 7-Day Trial",
"inNoSpaces": "You are not a member of any spaces",
"successfullySubscribed": "You have successfully subscribed!",
"clickToManageSubscription": "Click here to manage your subscription.",
"emptyInviteWarning": "Add this chat to a space to invite other users.",
"errorGettingAudio": "Error getting audio. Please refresh and try again.",
"signUp": "Sign up",
"pleaseChooseAtLeastChars": "Please choose at least {min} characters.",
@ -4065,8 +4015,6 @@
},
"noEmailWarning": "Please enter a valid email address. Otherwise you won't be able to reset your password. If you don't want to, tap again on the button to continue.",
"pleaseEnterValidEmail": "Please enter a valid email address.",
"noAddToSpacePermissions": "You can't add a chat to this space",
"alreadyInSpace": "The chat is already in this space",
"pleaseChooseAUsername": "Please choose a username",
"chooseAUsername": "Choose a username",
"define": "Define",
@ -4157,36 +4105,27 @@
"runGrammarCorrection": "Check message",
"grammarCorrectionFailed": "Issues to address",
"grammarCorrectionComplete": "Looks good!",
"tooltipInstructionsTitle": "Not sure what that does?",
"tooltipInstructionsMobileBody": "Press and hold items to view tooltips.",
"tooltipInstructionsBrowserBody": "Hover over items to view tooltips.",
"addSpaceToSpaceDescription": "Select a space to add as a parent",
"chatCapacity": "Chat capacity",
"spaceCapacity": "Space capacity",
"roomFull": "This room is already at capacity.",
"topicNotSet": "The topic has not been set.",
"chatCapacityNotSet": "This chat has no capacity limit.",
"spaceCapacityNotSet": "This space has no capacity limit.",
"chatCapacityHasBeenChanged": "Chat capacity changed",
"spaceCapacityHasBeenChanged": "Space capacity changed",
"chatCapacitySetTooLow": "Chat capacity cannot be set below the current number of members.",
"spaceCapacitySetTooLow": "Space capacity cannot be set below the current number of members.",
"chatCapacitySetTooLow": "Chat capacity must be at least {count}.",
"@chatCapacitySetTooLow": {
"type": "int",
"placeholders": {
"count": {
"type": "int"
}
}
},
"chatCapacityExplanation": "Chat capacity limits the number of members allowed in a chat.",
"spaceCapacityExplanation": "Space capacity limits the number of members allowed in a space.",
"chatExceedsCapacity": "This chat exceeds its capacity.",
"spaceExceedsCapacity": "This space exceeds its capacity.",
"tooManyRequest": "Too many request, please try again later.",
"enterNumber": "Please enter a whole number value.",
"buildTranslation": "Build your translation from the choices above",
"nonexistentSelection": "Selection no longer exists.",
"cantAddSpaceChild": "You do not have permission to add a child to this space.",
"roomAddedToSpace": "Room(s) have been added to the selected space.",
"addChatToSpaceDesc": "Adding a chat to a space will make the chat appear within the space for students and give them access.",
"addSpaceToSpaceDesc": "Adding a sub space to space will make the sub space appear in the main space's chat list.",
"spaceAnalytics": "Space Analytics",
"changeAnalyticsLanguage": "Change Analytics Language",
"suggestToSpace": "Suggest this space",
"suggestToSpaceDesc": "Suggested sub spaces will appear in their main space's chat list",
"practice": "Practice",
"noLanguagesSet": "No languages set",
"noActivitiesFound": "That's enough on this for now! Come back later for more.",
@ -4226,8 +4165,6 @@
"deleteSubscriptionWarningTitle": "You have an active subscription",
"deleteSubscriptionWarningBody": "Deleting your account will not automatically cancel your subscription.",
"manageSubscription": "Manage Subscription",
"createSpace": "Create space",
"createChat": "Create chat",
"error520Title": "Please try again.",
"error520Desc": "Sorry, we could not understand your message...",
"wordsUsed": "Words Used",
@ -4244,13 +4181,10 @@
"feedback": "Optional feedback",
"reportContentIssueDescription": "Uh oh! AI can faciliate personalized learning experiences but... also hallucinates. Please provide any feedback you have and we'll try again.",
"changeContent": "Uh oh! AI can faciliate personalized learning experiences but... also hallucinates. What should it be?",
"clickTheWordAgainToDeselect": "Click the selected word to deselect it.",
"l2SupportNa": "Not Available",
"l2SupportAlpha": "Alpha",
"l2SupportBeta": "Beta",
"l2SupportFull": "Full",
"missingVoiceTitle": "Missing voice",
"voiceNotAvailable": "You don't have a voice installed for this language.",
"openVoiceSettings": "Open voice settings",
"playAudio": "Play",
"stop": "Stop",
@ -4514,9 +4448,10 @@
"grammarCopyPUNCTTYPEperi": "Period",
"grammarCopyREFLEXyes": "Reflexive",
"grammarCopyTENSEimp": "Imperfect",
"grammarCopyVERBFORMsup": "SuApine",
"grammarCopyVERBFORMsup": "Supine",
"grammarCopyVERBFORMadn": "Adnominal",
"grammarCopyVERBFORMlng": "Long",
"grammarCopyVERBFORMshrt": "Short",
"grammarCopyVERBTYPEcaus": "Causative Verb",
"grammarCopyVOICEcau": "Causative",
"grammarCopyVOICEdir": "Direct",
@ -4540,25 +4475,20 @@
}
},
"botModeValidation": "Please select a chat mode",
"clickBestOption": "Choose the best options to translate your message!",
"clickBestOption": "Choose the best options to translate your message! Click and hold options for a hint.",
"completeActivitiesToUnlock": "Complete at least one activity to unlock the translation!",
"botSettingsSubtitle": "Invite bot to moderate chat activity",
"invitePeople": "Invite users",
"noCapacityLimit": "No capacity limit",
"downloadGroupText": "Download group text",
"spaceDescription": "Space description",
"addSpaceDescription": "Add a space description",
"notificationsOn": "Notifications on",
"notificationsOff": "Notifications off",
"spaceCanBeFoundViaSearch": "Space can be found via search",
"chatCanBeFoundViaSearch": "Chat can be found via search",
"requireCodeToJoin": "Require code to join",
"canFindInSearch": "Can find in search",
"addSubspaceWarning": "Once you add this, it will not appear in public search results, and it will be visible to all members of the parent space.",
"nestedSpaceError": "Spaces should not be added as children of other spaces",
"addChatToSpace": "Add chat",
"createChatAndInviteUsers": "Create chat and invite users",
"updatedNewSpaceDescription": "Spaces allow you to consolidate your chats and build private or public communities.",
"updatedNewSpaceDescription": "Courses allow you to consolidate your chats and build private or public communities.",
"joinWithCode": "Join with code",
"enterCodeToJoin": "Enter code to join",
"updateNow": "Update Now",
@ -4589,6 +4519,7 @@
"constructUseIncMDesc": "Incorrect in grammar activity",
"constructUseIgnMDesc": "Ignored in grammar activity",
"constructUseEmojiDesc": "Correct in emoji activity",
"constructUseCollected": "Collected in chat",
"constructUseNanDesc": "Not applicable",
"xpIntoLevel": "{currentXP} / {maxXP} XP",
"@xpIntoLevel": {
@ -4630,9 +4561,9 @@
"meaningSectionHeader": "Meaning:",
"formSectionHeader": "Forms used in chats:",
"noEmojiSelectedTooltip": "No emoji selected",
"writingExercisesTooltip": "Writing practice",
"listeningExercisesTooltip": "Listening practice",
"readingExercisesTooltip": "Reading practice",
"writingExercisesTooltip": "Writing",
"listeningExercisesTooltip": "Listening",
"readingExercisesTooltip": "Reading",
"meaningNotFound": "Meaning could not be found.",
"formsNotFound": "Forms could not be found.",
"chooseBaseForm": "Choose the base form",
@ -4658,7 +4589,6 @@
"numWordsTyped": "Number of words typed in original messages",
"numCorrectChoices": "Number of correct words chosen from system-generated suggestions",
"numIncorrectChoices": "Number of incorrect words chosen from system-generated suggestions",
"downloadSpaceAnalytics": "Download space analytics",
"commaSeparatedFile": "CSV",
"excelFile": "Excel",
"fileType": "File type",
@ -4717,8 +4647,6 @@
}
}
},
"notInClass": "Not in a class!",
"noClassCode": "No class code!",
"chooseCorrectLabel": "Choose the correct label.",
"levelPopupTitle": "Congratulations on reaching\nLevel {level}",
"@levelPopupTitle": {
@ -4732,7 +4660,7 @@
"activityPlannerTitle": "Activity Planner",
"topicLabel": "Topic",
"topicPlaceholder": "Choose a topic...",
"modeLabel": "Mode",
"modeLabel": "Activity type",
"modePlaceholder": "Choose a mode...",
"learningObjectiveLabel": "Learning Objective",
"learningObjectivePlaceholder": "Choose a learning objective...",
@ -4740,18 +4668,15 @@
"languageOfInstructionsLabel": "Language of activity instructions",
"targetLanguageLabel": "Target language",
"cefrLevelLabel": "CEFR level",
"generateActivitiesButton": "Generate Activities",
"generateActivitiesButton": "Generate Activity",
"launchActivityButton": "Launch Activity",
"image": "Image",
"video": "Video",
"nan": "Not applicable",
"activityPlannerOverviewInstructionsBody": "Choose a topic, mode, learning objective and generate an activity for the chat!",
"myBookmarkedActivities": "My Bookmarked Activities",
"noBookmarkedActivities": "No bookmarked activities",
"activityTitle": "Activity Title",
"addVocabulary": "Add vocabulary",
"instructions": "Instructions",
"bookmark": "Bookmark this activity",
"numberOfLearners": "Number of learners",
"mustBeInteger": "Must be an integer e.g. 1, 2, 3, ...",
"noLemmasFound": "There's no vocabulary with more than {xp} XP. Keep practicing!",
@ -4765,7 +4690,7 @@
},
"constructUsePvmDesc": "Produced in voice message",
"lockedMorphFeature": "Waiting to be unlocked",
"leaveSpaceDescription": "By leaving the space, you will leave all of the chats within it. Other users will see that you have left the space.",
"leaveSpaceDescription": "By leaving the course, you will leave all of the chats within it. Other users will see that you have left the course.",
"whatIsLemma": "What is the lemma?",
"constructUseCorMmDesc": "Correct message meaning",
"constructUseIncMmDesc": "Incorrect message meaning",
@ -4782,14 +4707,14 @@
}
},
"slightlyOffensive": "Slightly offensive",
"clickOnEmailLink": "Please click on the link in the email and then proceed. In rare cases, the email can be sent to spam or take up to 5 minutes to arrive.",
"clickOnEmailLink": "Please click on the link in the email and then proceed.\n\nCheck your spam folder if the email hasn't arrived.",
"whoIsAllowedToJoinThisChat": "Who is allowed to join this chat",
"dontForgetPassword": "Don't forget your password!",
"enableAutocorrectToolName": "Enable device autocorrect",
"enableAutocorrectDescription": "If your device supports the language your learning, you can enable device autocorrect to fix common errors as you type.",
"enableAutocorrectDescription": "If your device supports the language you're learning, you can enable device autocorrect to fix common errors as you type.",
"ttsDisbledTitle": "Text-to-speech disabled",
"ttsDisabledBody": "You can enable text-to-speech in your learning settings",
"noSpaceDescriptionYet": "No space description created yet.",
"noSpaceDescriptionYet": "No course description created yet.",
"tooLargeToSend": "This message is too large to send",
"exitWithoutSaving": "Are you sure you want to leave without saving?",
"enableAutocorrectPopupTitle": "Add your target language keyboard by going to:",
@ -4828,7 +4753,7 @@
"autocorrectNotAvailable": "Unfortunately your platform is not currently supported for this feature. Stay tuned for further development!",
"pleaseUpdateApp": "Please update the app to continue.",
"chooseEmojiInstructionsBody": "Match emojis with the words they best represent. Don't worry! No points off for disagreeing. 😅",
"pickAnEmojiFor": "Pick an emoji for ${lemma}",
"pickAnEmojiFor": "Pick an emoji for {lemma}",
"@pickAnEmojiFor": {
"type": "String",
"placeholders": {
@ -4839,9 +4764,8 @@
},
"analyticsVocabListBody": "This is all your vocabulary! As you earn XP for each word, they'll go from seedling to full bloom. Click on any word to see more details.",
"morphAnalyticsListBody": "These are all the grammar concepts in the language you're learning! You'll unlock them as you encounter them while chatting. Click for details.",
"knockSpaceSuccess": "You have requested to join this space! An admin will respond to your request when they receive it 😀",
"knockSpaceSuccess": "You have requested to join this course! An admin will respond to your request when they receive it 😀",
"joinByCode": "Join by code",
"createASpace": "Create a space",
"chooseWordAudioInstructionsBody": "Listen to the complete message. Then match the audios with the words.",
"chooseMorphsInstructionsBody": "Click the puzzle pieces for grammar questions!",
"inviteAndLaunch": "Launch and invite",
@ -4873,16 +4797,14 @@
"exploreMore": "Explore more",
"randomize": "Randomize",
"clear": "Clear",
"makeYourOwnActivity": "Make your own activity",
"makeYourOwnActivity": "Create your own activity",
"featuredActivities": "Featured",
"yourBookmarks": "Bookmarked",
"goToChat": "Go to chat",
"save": "Save",
"selectActivity": "Select activity",
"newChatActivityDesc": "Make every group chat an adventure with Activity Planner! Set captivating topics and objectives for the group, and bring conversations to life with stunning images. Spark imaginative discussions and keep the fun flowing effortlessly!",
"exploreMore": "Explore more",
"wordFocusListeningMultipleChoice": "Which audio matches the word?",
"createActivity": "Create activity",
"startChat": "Start a chat",
"translationProblem": "Translation problem",
"perfectTranslation": "Perfect translation!",
@ -4891,19 +4813,18 @@
"makingProgress": "You're making progress!",
"keepPracticing": "Keep practicing!",
"niceJob": "Nice job!",
"publicSpacesTitle": "Learning communities",
"askToJoin": "Ask to join",
"emptyChatWarningTitle": "Chat is empty",
"emptyChatWarningDesc": "You haven't invited anyone to your chat. Go to Chat settings to invite your contacts or the Bot. You can also do this later.",
"areYouLikeMe": "Are you like me?",
"tryAgainLater": "Too many attempts made. Please try again in 5 minutes.",
"enterSpaceCode": "Enter space code",
"enterSpaceCode": "Enter course code",
"shareSpaceLink": "Share link",
"byUsingPangeaChat": "By using Pangea Chat, I agree to the ",
"details": "Details",
"languageLevelPreA1Desc": "I have never learned or used the language.",
"languageLevelA1Desc": "I can understand and use some familiar everyday expressions and very basic phrases.",
"languageLevelA2Desc": "I can understand sentences and frequently used expressions related to areas of immediate relevance",
"languageLevelA2Desc": "I can understand sentences and frequently used expressions related to areas of immediate relevance.",
"languageLevelB1Desc": "I can deal with most familiar situations and can produce simple connected text on familiar topics.",
"languageLevelB2Desc": "I can understand the mains ideas of complex texts and interact with a degree of fluency and spontaneity.",
"languageLevelC1Desc": "I can express ideas fluently and spontaneously without much struggle and understand a wide range of demanding texts.",
@ -4920,14 +4841,6 @@
},
"seeDetails": "See Details",
"choosePracticeMode": "Click on one of the buttons above to start a practice activity",
"userWouldLikeToChangeTheSpace": "{user} would like to join the space.",
"@userWouldLikeToChangeTheSpace": {
"placeholders": {
"user": {
"type": "String"
}
}
},
"ban": "Ban",
"unban": "Unban",
"kick": "Kick",
@ -4938,7 +4851,6 @@
"exampleMessages": "Example messages",
"timesUsedIndependently": "Times used independently",
"timesUsedWithAssistance": "Times used with assistance",
"goToSpaceButton": "Go to space",
"shareInviteCode": "Share invite code: {code}",
"@shareInviteCode": {
"placeholders": {
@ -4956,58 +4868,56 @@
}
}
},
"joinSpaceOnboardingDesc": "Do you have an invite code or link to a learning community?",
"joinSpaceOnboardingDesc": "Do you have an invite code or link to a public course?",
"skipForNow": "Skip for now",
"permissions": "Permissions",
"spaceChildPermission": "Who can add new chats and subspaces to this space",
"spaceChildPermission": "Who can add new chats to this course",
"addEnvironmentOverride": "Add environment override",
"defaultOption": "Default",
"deleteChatDesc": "Are you sure you want to delete this chat? It will be deleted for all participants and all messages within the chat will no longer be available for practice or learning analytics.",
"deleteSpaceDesc": "The space and any selected chats and/or subspaces will be deleted for all participants and all messages within the chat will no longer be available for practice or learning analytics. This action cannot be undone.",
"deleteSpaceDesc": "The course and any selected chats will be deleted for all participants and all messages within the chat will no longer be available for practice or learning analytics. This action cannot be undone.",
"chatWithActivities": "Chat with activities",
"findYourPeople": "Find your people",
"launch": "Launch",
"launchActivityToChats": "Launch activity to chats",
"searchChats": "Search chats",
"selectChats": "Select chats",
"selectChatToStart": "Complete! Select a chat to start",
"maxFifty": "Max 50",
"configureSpace": "Configure space",
"configureSpace": "Configure course",
"pinMessages": "Pin messages",
"setJoinRules": "Set join rules",
"changeGeneralSettings": "Change general settings",
"inviteOtherUsersToRoom": "Invite other users",
"changeTheNameOfTheSpace": "Change the name of the space",
"changeTheNameOfTheSpace": "Change the name of the course",
"changeTheDescription": "Change the description",
"changeThePermissions": "Change the permissions",
"introductions": "Introductions",
"announcements": "Announcements",
"activities": "Activities",
"access": "Access",
"addSubspace": "Add subspace",
"botSettings": "Bot settings",
"activitySuggestionTimeoutMessage": "We are working hard to generate activities for you, please check back in a minute",
"activitySuggestionTimeoutMessage": "We are working hard to generate more activities for you, please check back in a minute",
"accessSettingsWarning": "Oops! It looks like you don't have permission to set the Access rules of this room. You should check these to make sure they're what you need and talk to a room admin if you need to change them",
"howSpaceCanBeFound": "How this space can be found",
"howSpaceCanBeFound": "How this course can be found",
"private": "Private",
"cannotBeFoundInSearch": "Cannot be found in search",
"public": "Public",
"visibleToCommunity": "Visible to the broader Pangea Chat community via \"Find your people\"",
"howSpaceCanBeJoined": "How this space can be joined",
"visibleToCommunity": "Visible to the broader Pangea Chat community via \"Find a course\"",
"howSpaceCanBeJoined": "How this course can be joined",
"restricted": "Restricted",
"canBeFoundVia": "Can be found via:",
"canBeFoundViaInvitation": "\u2022 invitation",
"canBeFoundViaCodeOrLink": "\u2022 code or link",
"canBeFoundViaKnock": "\u2022 request to join and admin approval",
"anyoneCanJoin": "Anyone can join! However, admin can kick and ban whoever misbehaves. Those who are banned may not return!",
"createYourSpace": "Create your space",
"youHaveLeveledUp": "You have leveled up!",
"sendActivities": "Send activities",
"getStarted": "Get Started",
"getStartedBotChatDesc": "Chatting with AI is a great place to start and Pangea reading, writing, listening and speaking tools make it easy!",
"getStartedCommunitiesDesc": "Learning with a community is where Pangea Chat shines!\nYou can join your class, find a school, or even make your own!",
"getStartedCommunitiesDesc": "Learning with a community is where Pangea Chat shines!\nYou can join your class, find a course, or even make your own!",
"getStartedFriendsDesc": "Do you have a friend that wants to learn with you?",
"getStartedBotChatComplete": "Well-done! You're chatting with the bot!",
"getStartedCommunitiesComplete": "Great, you have joined a space!",
"getStartedCommunitiesComplete": "Great, you have joined a course!",
"getStartedComplete": "You've completed this section!\nKeep exploring our amazing features by chatting with friends!",
"getStartedFriendsComplete": "Woohoo! You've got friends! 😉",
"getStartedBotChatButton": "Start chatting!",
@ -5015,12 +4925,12 @@
"groupChat": "Group Chat",
"directMessage": "Direct Message",
"newDirectMessage": "New direct message",
"speakingExercisesTooltip": "Speaking practice",
"speakingExercisesTooltip": "Speaking",
"noChatsFoundHereYet": "No chats found here yet",
"duration": "Duration",
"transcriptionFailed": "Failed to transcribe audio",
"aUserIsKnocking": "1 user is requesting to join your space",
"usersAreKnocking": "{users} users are requesting to join your space",
"aUserIsKnocking": "1 user is requesting to join your course",
"usersAreKnocking": "{users} users are requesting to join your course",
"@usersAreKnocking": {
"type": "int",
"placeholders": {
@ -5030,5 +4940,370 @@
}
},
"failedToFetchTranscription": "Failed to fetch transcription",
"deleteEmptySpaceDesc": "The space will be deleted for all participants. This action cannot be undone."
}
"deleteEmptySpaceDesc": "The course will be deleted for all participants. This action cannot be undone.",
"customReaction": "Custom reaction",
"regenerate": "Regenerate",
"mySavedActivities": "My Saved Activities",
"noSavedActivities": "No saved activities",
"saveActivity": "Save this activity",
"yourSavedActivities": "Saved Activities",
"failedToPlayVideo": "Failed to play video",
"done": "Done",
"inThisSpace": "In this course",
"myContacts": "My contacts",
"inviteAllInSpace": "Invite all in this course",
"spaceParticipantsHaveBeenInvitedToTheChat": "All course participants has been invited to the chat",
"numKnocking": "{count} knocking",
"@numKnocking": {
"type": "String",
"placeholders": {
"count": {
"type": "int"
}
}
},
"numInvited": "{count} invited",
"@numInvited": {
"type": "String",
"placeholders": {
"count": {
"type": "int"
}
}
},
"saved": "Saved",
"reset": "Reset",
"errorGenerateActivityMessage": "Failed to generate activity",
"errorRegenerateActivityMessage": "Failed to regenerate activity",
"errorLaunchActivityMessage": "Failed to launch activity",
"errorFetchingActivitiesMessage": "Failed to fetch activities",
"errorFetchingDefinition": "Failed to fetch definition",
"errorProcessAnalytics": "Failed to process analytics",
"errorDownloading": "Download failed",
"errorFetchingLevelSummary": "Failed to fetch level summary",
"errorLoadingSpaceChildren": "Failed to load chats within this course",
"unexpectedError": "Unexpected error.",
"pleaseReload": "Please reload and try again.",
"translationError": "Translation error",
"errorFetchingTranslation": "Failed to fetch translation",
"errorFetchingActivity": "Failed to fetch activity",
"check": "Check",
"unableToFindRoom": "No chat or course found with that code. Please try again.",
"numCompletedActivities": "Number of completed activities",
"viewingAnalytics": "Viewing {visible}/{users} Analytics",
"@viewingAnalytics": {
"type": "String",
"placeholders": {
"visible": {
"type": "int"
},
"users": {
"type": "int"
}
}
},
"request": "Request",
"requestAll": "Request All",
"confirmMessageUnpin": "Are you sure you want to unpin this message?",
"createActivityPlan": "Create a new activity plan",
"saveAndLaunch": "Save and Launch",
"launchToSpace": "Launch to course",
"numberOfActivities": "Number of Activity Sessions",
"maximumActivityParticipants": "Each Activity can have a maximum of {count} participant(s).",
"@maximumActivityParticipants": {
"type": "String",
"placeholders": {
"count": {
"type": "int"
}
}
},
"pending": "Pending",
"inactive": "Inactive",
"unjoinedActivityMessage": "Do you want to participate? Choose an open role!\nOr hang out and watch the show!",
"fullActivityMessage": "Feel free to watch the show! While there aren't any open roles to participate, you can view the chat!",
"confirmRole": "Confirm role",
"openRoleLabel": "OPEN",
"joinedTheActivity": "👋 {username} joined as {role}",
"@joinedTheActivity": {
"type": "String",
"placeholders": {
"username": {
"type": "String"
},
"role": {
"type": "String"
}
}
},
"finishedTheActivity": "🎯 {username} wrapped up this activity",
"@finishedTheActivity": {
"type": "String",
"placeholders": {
"username": {
"type": "String"
}
}
},
"endActivityTitle": "I'm done",
"endActivityDesc": "Did you complete the objectives?\nThis is your confirmation that you're stepping back from texting. But dont worry, the fun continues in the chat! Feel free to hang out and enjoy the show until everyone clicks 'Done'.",
"archiveToAnalytics": "Add to my Completed Activities",
"activitySummaryError": "Activity summaries unavailable",
"requestSummaries": "Request summaries",
"loadingActivitySummary": "Loading activity summary...",
"generatingNewActivities": "You're the first user of this language pair! Please give us a minute, we're preparing activities just for you.",
"requestAccessTitle": "Request to analytics view access?",
"requestAccessDesc": "Would you like to request access to view participant analytics?\n\nIf participants agree, admins of this course will be able to view their:\n • total vocabulary\n • total grammar concepts\n • total activity sessions completed\n • the specific grammar concepts used, correctly and incorrectly\n\nThey will not be able to view their:\n • messages in chats outside the course\n • vocabulary list",
"requestAccess": "Request access ({count})",
"@requestAccess": {
"type": "String",
"placeholders": {
"count": {
"type": "int"
}
}
},
"analyticsInactiveTitle": "Requests to inactive users couldnt be sent",
"analyticsInactiveDesc": "Inactive users who haven't logged in since this feature was introduced won't see your request.\n\nThe Request button will appear once they return. You can resend the request later by clicking the Request button under their name when it's available.",
"accessRequestedTitle": "Analytics Access Request",
"accessRequestedDesc": "The administrators of “{space}” are requesting to view your learning analytics.\n\nIf you agree, admins of this course will be able to view your:\n • total vocabulary\n • total grammar concepts\n • total activity sessions completed\n • the specific grammar concepts used, correctly and incorrectly\n\nThey will not be able to view your:\n • messages in chats outside the course\n • vocabulary list",
"@accessRequestedDesc": {
"type": "String",
"placeholders": {
"space": {
"type": "String"
}
}
},
"allowAccess": "Allow Access",
"denyAccess": "Deny Access",
"adminRequestedAccess": "Admins asked to view your analytics.",
"lastUpdated": "Updated\n{time}",
"@lastUpdated": {
"type": "String",
"placeholders": {
"time": {
"type": "String"
}
}
},
"activityFinishedMessage": "All Finished!",
"endForAll": "End for all",
"newCourse": "New Course",
"newCourseSubtitle": "Which course plan plan would you like to use?",
"failedToLoadCourses": "Failed to load courses",
"numModules": "{num} modules",
"@numModules": {
"type": "int",
"placeholders": {
"num": {
"type": "int"
}
}
},
"numActivityPlans": "{num} activity plans",
"@numActivityPlans": {
"type": "int",
"placeholders": {
"num": {
"type": "int"
}
}
},
"coursePlan": "Course Plan",
"editCourseLater": "You can edit template title, descriptions, and course image later.",
"newCourseAccess": "By default, courses are private and require admin approval to join. You can edit these settings at any time.",
"createCourse": "Create course",
"stats": "Stats",
"createGroupChat": "Create group chat",
"editCourse": "Edit course",
"inviteDesc": "By username, by code or link",
"editCourseDesc": "Here you can edit course title, description, etc.",
"permissionsDesc": "Set permissions such as who can invite users, send messages, create chats, etc.",
"accessDesc": "You can make your course open to the world! Or, make your course private and secure.",
"createGroupChatDesc": "Whereas activity sessions start and end, group chats will stay open for routine communication.",
"deleteDesc": "Only admins can delete a course. This is a destructive action which removes all users and deletes all selected chats within the course. Proceed with caution.",
"failedToLoadCourseInfo": "Failed to load course information",
"noCourseFound": "Oh, this course needs a plan!\n\nCourse plans are a sequence of topics and conversation activities.",
"additionalParticipants": "+ {num} others",
"@additionalParticipants": {
"type": "int",
"placeholders": {
"num": {
"type": "int"
}
}
},
"activityNotFoundForCourse": "This activity was not found within the course",
"courseChats": "Course Chats",
"myActivitySessions": "My Activity Sessions",
"directMessages": "Direct Messages",
"whatNow": "What now?",
"chooseNextActivity": "Choose your next activity!",
"seeInstructions": "See Instructions",
"hideInstructions": "Hide Instructions",
"letsGo": "Lets go!",
"chooseRole": "Choose a role!",
"chooseRoleToParticipate": "Choose a role to participate!",
"waitingToFillRole": "Waiting to fill {num} roles...",
"@waitingToFillRole": {
"type": "int",
"placeholders": {
"num": {
"type": "int"
}
}
},
"pingParticipants": "Ping course participants",
"playWithBot": "Play with Pangea Bot",
"inviteFriendsToActivity": "Invite friends to activity",
"inviteFriendsToActivityCourse": "Invite friends to activity and course",
"waitNotDone": "Wait Im not done!",
"waitingForOthersToFinish": "Waiting for the rest to finish up...",
"saveToCompletedActivities": "Save to completed activities",
"generatingSummary": "Analyzing chat and generating results",
"instructionsLanguage": "Instructions language",
"activityCompletedDesc": "Your completed activity was added to analytics where you can review and practice the language you used.",
"pingParticipantsNotification": "{user} is looking for users to join the activity session in {room}",
"@pingParticipantsNotification": {
"type": "String",
"placeholders": {
"user": {
"type": "String"
},
"room": {
"type": "String"
}
}
},
"course": "Course",
"courses": "Courses",
"courseName": "Course name",
"createNewCourse": "New course",
"newCourse": "New course",
"publicCourses": "Public courses",
"goToCourse": "Go to course: {course}",
"@goToCourse": {
"type": "String",
"course": {}
},
"activityComplete": "This activity has been completed. The activity summary should be available below.",
"haventChattedMuch": "It looks like you haven't chatted much, try using some more vocab words! If you feel like you've completed your objective, you can end the activity below.",
"haveChatted": "It looks like you've been chatting for a while! If you feel like you've completed your objective, wrap up to finish the activity and we'll generate you a summary in the chat!",
"userDoneAndWaiting": "{num1}/{num2} participants have wrapped up. Wait for everyone to finish, and we'll generate you a summary in the chat! \n\nIf you'd like to rejoin the conversation, click the continue button in the chat.",
"@userDoneAndWaiting": {
"placeholders": {
"num1": {
"type": "int"
},
"num2": {
"type": "int"
}
}
},
"othersDoneAndWaiting": "{num1}/{num2} are done. Have you completed your objective?",
"@othersDoneAndWaiting": {
"placeholders": {
"num1": {
"type": "int"
},
"num2": {
"type": "int"
}
}
},
"startNewSession": "Start new session",
"joinOpenSession": "Join open session",
"less": "less",
"activityNotFound": "Activity not found",
"levelUp": "Level up",
"myActivities": "My activities",
"openToJoin": "Open to join",
"results": "Results",
"activityDone": "Activity Done!",
"moreLabel": "more",
"promoCodeInfo": "Promo codes can be entered on the next page",
"editsComingSoon": "The ability to edit cities and activities is coming soon.",
"editing": "Editing",
"activityNeedsOneMember": "Uh oh! This activity needs 1 more person.",
"activityNeedsMembers": "Uh oh! This activity needs {num} more people.",
"@activityNeedsMembers": {
"placeholders": {
"num": {
"type": "int"
}
}
},
"inviteFriendsToCourse": "Invite friends to my course",
"subscribeToUnlockActivitySummaries": "Subscribe to unlock activity summaries",
"subscribeToUnlockDefinitions": "Subscribe to unlock definitions",
"subscribeToUnlockTranscriptions": "Subscribe to unlock transcriptions",
"pingSent": "🔔 Course ping sent! 🔔",
"courseTitle": "Course title",
"courseDesc": "Course description",
"courseSavedSuccessfully": "Course saved successfully",
"addCoursePlan": "Add a course plan",
"activityStatsButtonInstruction": "Click here to view your activity stats and to close the activity when finished",
"readingAnalyticsDesc": "Click practice on each message for reading activities.",
"speakingAnalyticsDesc": "Record voice messages for speaking practice.",
"audioAnalyticsDesc": "Click practice on each message for listening activities.",
"loginToAccount": "Login to my account",
"appDescription": "Learn a language\nwhile texting your friends.",
"languages": "Languages",
"chooseLanguage": "Choose a target language.",
"letsGo": "Let's go",
"startOwn": "Start my own",
"joinCourseDesc": "Each course has 8-10 sequenced topics with a range of task-based language learning activities.",
"courseCodeHint": "Course code",
"anyLevel": "Any Level",
"signupOption": "How do you want to sign up?",
"withApple": "With Apple",
"withGoogle": "With Google",
"withEmail": "With Email",
"createAccount": "Create account",
"noCoursesFound": "No courses found",
"loginWithEmail": "Login with email",
"usernameOrEmail": "Username or email",
"email": "Email",
"forgotPassword": "Forgot password?",
"writingAnalyticsDesc": "Send messages to practice writing.",
"endActivity": "End activity",
"allLanguages": "All languages",
"allCefrLevels": "All CEFR levels",
"chatListTooltip": "Here youll find your direct messages! Click on any users avatar and “start conversation” to send a DM.",
"directMessageBotTitle": "Direct message Pangea Bot",
"feedbackTitle": "Activity Feedback",
"feedbackDesc": "How should the activity be improved? If you can provide some details, well make the change!",
"feedbackRespDesc": "Check back tomorrow for activity updates.",
"feedbackHint": "Your feedback",
"feedbackButton": "Submit feedback",
"directMessageBotDesc": "Talking to humans is more fun but... AI is always ready!",
"inviteYourFriends": "Invite your friends",
"playWithAI": "Play with AI for now",
"courseStartDesc": "Pangea Bot is ready to go anytime!\n\n...but learning is better with friends!",
"activityDropdownDesc": "When youre done with this activity, click below",
"activityAnalyticsListBody": "These are your completed activities! After finishing activities, you can view them here.",
"languageMismatchTitle": "Language mismatch",
"languageMismatchDesc": "Your target language doesn't match the language of this activity. Update your target language?",
"reportWordIssueTooltip": "Report word information issue",
"tokenInfoFeedbackDialogTitle": "Word Information Feedback",
"tokenInfoFeedbackDialogDesc": "AI makes mistakes. Please describe any issues you found with the information above.",
"noPublicCoursesFound": "No public courses found. Would you like to create one?",
"noCourseTemplatesFound": "We couldn't find any courses for your target language. You can chat with Pangea Bot in the meantime, and check back later for more courses.",
"botActivityJoinFailMessage": "Pangea Bot is taking a while to respond. Please try again later, or invite a friend.",
"unsubscribedResponseError": "This feature requires a subscription",
"leaveDesc": "Leave this space and all chats within it",
"selectAll": "Select all",
"deselectAll": "Deselect all",
"newMessageInPangeaChat": "💬 New message in Pangea Chat",
"shareCourse": "Share course",
"@shareCourse": {
"type": "String",
"placeholders": {}
},
"addCourse": "Add a course",
"joinCourseWithCode": "Join course with code",
"joinPublicCourse": "Join public course",
"vocabLevelsDesc": "This is where vocab words will go once youve leveled them up!",
"highlightVocabTooltip": "Highlight target vocab words below by sending them or practicing with them in the chat"
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more