Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/jest-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Jest Tests

on:
push:
branches:
- main
pull_request:

concurrency:
group: jest-tests-${{ format('{0}-{1}', github.head_ref || github.run_number, github.job) }}
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: 24
cache: yarn

- name: Yarn install
run: yarn

- name: Jest
run: yarn test:unit
7 changes: 1 addition & 6 deletions e2e/onboarding.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
/*global describe*/
/*global beforeAll*/
/*global beforeEach*/
/*global it*/

import { by, device, element, expect } from 'detox';
import i18n from 'i18n-js';

Expand Down Expand Up @@ -42,7 +37,7 @@ describe.each([['en'], ['fr']])(`Onboarding (locale: %s)`, locale => {

it('should show the Discover screen', async () => {
await element(by.text(i18n.t('discover'))).tap();
await expect(element(by.text(i18n.t('discover_all')))).toBeVisible();
await expect(element(by.text(i18n.t('discover_pick_tag')))).toBeVisible();
});

it('should show the Notifications screen', async () => {
Expand Down
5 changes: 0 additions & 5 deletions e2e/topiclist.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
/*global describe*/
/*global beforeAll*/
/*global beforeEach*/
/*global it*/

import i18n from 'i18n-js';

import { by, device, element, expect } from 'detox';
Expand Down
8 changes: 8 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,13 @@ export default [
'no-undef': 'warn',
},
},
{
files: ['**/__tests__/**/*.js', '**/*.test.js'],
languageOptions: {
globals: {
...globals.jest,
},
},
},
{ ignores: ['lib/*', 'react-native.config.js', '.*', '*.config.js'] },
];
12 changes: 6 additions & 6 deletions fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ fastlane_require "base64"
fastlane_require "fileutils"
fastlane_require "json"

IOS_APP_VERSION = "2.1.5"
ANDROID_APP_VERSION = "2.1.2" # run `fastlane bootstrap` after editing this
IOS_APP_VERSION = "2.2.0"
ANDROID_APP_VERSION = "2.2.0" # run `fastlane bootstrap` after editing this
PROJECT_NAME = "Discourse"
IOS_TEAM_ID = "6T3LU73T8S"
KEYS_REPOSITORY = "git@github.com:discourse-org/discourse-mobile-keys.git"
Expand Down Expand Up @@ -172,8 +172,8 @@ platform :ios do
export_method: "app-store",
export_options: {
provisioningProfiles: {
"org.discourse.DiscourseApp" => "match AppStore org.discourse.DiscourseApp",
"org.discourse.DiscourseApp.ShareExtension" => "match AppStore org.discourse.DiscourseApp.ShareExtension"
"org.discourse.DiscourseApp" => "match AppStore org.discourse.DiscourseApp 1776778136",
"org.discourse.DiscourseApp.ShareExtension" => "match AppStore org.discourse.DiscourseApp.ShareExtension 1776778138"
}
},
clean: true,
Expand All @@ -194,8 +194,8 @@ platform :ios do
export_method: "ad-hoc",
export_options: {
provisioningProfiles: {
"org.discourse.DiscourseApp" => "match AdHoc org.discourse.DiscourseApp",
"org.discourse.DiscourseApp.ShareExtension" => "match AdHoc org.discourse.DiscourseApp.ShareExtension"
"org.discourse.DiscourseApp" => "match AdHoc org.discourse.DiscourseApp 1776778144",
"org.discourse.DiscourseApp.ShareExtension" => "match AdHoc org.discourse.DiscourseApp.ShareExtension 1776778146"
}
},
clean: true,
Expand Down
22 changes: 8 additions & 14 deletions ios/Discourse.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 660;
CURRENT_PROJECT_VERSION = 671;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 6T3LU73T8S;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 6T3LU73T8S;
Expand All @@ -498,7 +498,7 @@
PRODUCT_BUNDLE_IDENTIFIER = org.discourse.DiscourseApp;
PRODUCT_NAME = Discourse;
PROVISIONING_PROFILE_SPECIFIER = "match AdHoc org.discourse.DiscourseApp";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc org.discourse.DiscourseApp";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc org.discourse.DiscourseApp 1776778144";
SWIFT_OBJC_BRIDGING_HEADER = "Discourse-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
Expand All @@ -516,7 +516,7 @@
CODE_SIGN_ENTITLEMENTS = Discourse/Discourse.entitlements;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 660;
CURRENT_PROJECT_VERSION = 671;
DEVELOPMENT_TEAM = 6T3LU73T8S;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 6T3LU73T8S;
ENABLE_BITCODE = NO;
Expand All @@ -543,7 +543,7 @@
PRODUCT_NAME = Discourse;
PROVISIONING_PROFILE = "8a5dde79-abbd-4707-a921-2b4412ef65ad";
PROVISIONING_PROFILE_SPECIFIER = "match AppStore org.discourse.DiscourseApp";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore org.discourse.DiscourseApp";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore org.discourse.DiscourseApp 1776778136";
SWIFT_OBJC_BRIDGING_HEADER = "Discourse-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
Expand Down Expand Up @@ -605,10 +605,7 @@
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)";
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
OTHER_LDFLAGS = "$(inherited) ";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
Expand Down Expand Up @@ -664,10 +661,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)";
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
OTHER_LDFLAGS = "$(inherited) ";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
Expand Down Expand Up @@ -702,7 +696,7 @@
PRODUCT_BUNDLE_IDENTIFIER = org.discourse.DiscourseApp.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match AdHoc org.discourse.DiscourseApp.ShareExtension";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc org.discourse.DiscourseApp.ShareExtension";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc org.discourse.DiscourseApp.ShareExtension 1776778146";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
Expand Down Expand Up @@ -737,7 +731,7 @@
PRODUCT_BUNDLE_IDENTIFIER = org.discourse.DiscourseApp.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match AdHoc org.discourse.DiscourseApp.ShareExtension";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore org.discourse.DiscourseApp.ShareExtension";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc org.discourse.DiscourseApp.ShareExtension 1776778146";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 5.0;
Expand Down
4 changes: 2 additions & 2 deletions ios/Discourse/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2.1.5</string>
<string>2.2.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
Expand All @@ -37,7 +37,7 @@
<dict/>
</array>
<key>CFBundleVersion</key>
<string>660</string>
<string>671</string>
<key>Fabric</key>
<dict>
<key>APIKey</key>
Expand Down
4 changes: 2 additions & 2 deletions ios/ShareExtension/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>2.1.5</string>
<string>2.2.0</string>
<key>CFBundleVersion</key>
<string>660</string>
<string>671</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
module.exports = {
preset: 'react-native',
testPathIgnorePatterns: ['/node_modules/', '/e2e/'],
};
14 changes: 13 additions & 1 deletion js/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@
"sites": "Sites",
"find_new_communities": "Find new communities to join",
"no_hot_topics": "No hot topics found for this site.",
"discover_communities": "Communities",
"discover_pick_tag": "What are you interested in?",
"discover_pick_tag_description": "See what people have been discussing in Discourse communities recently and join the ones that most match your interests.",
"discover_explore_more": "Explore another topic",
"discover_communities_section": "%{tag} Communities",
"discover_topics_section": "Recent Discussions in %{tag}",
Comment on lines +99 to +100
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One annoying thing is that we don't translate the tags themselves... so in other languages this will say "communautés gaming" for example... not sure how to fix it. I guess we could add tags as strings individually and that would allow translating them?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yeah, or we could have the endpoint in discover(hot-topics-tags.json) return the tag label too, then we could get rid of both:

export const PRIMARY_TAGS = [
{ tag: 'ai', label: 'ai' },
{ tag: 'technology', label: 'tech' },
{ tag: 'interests', label: 'interests' },
{ tag: 'support', label: 'support' },
{ tag: 'media', label: 'media' },
{ tag: 'gaming', label: 'gaming' },
{ tag: 'finance', label: 'finance' },
{ tag: 'open-source', label: 'open-source' },
];

and this issue at the same time

"discover_see_all_communities": "See all communities",
"discover_community_directory": "Community Directory",
"remove_from_home_screen": "Remove",
"preview": "Preview",
"community_recent_topics": "Hot Topics",
"oops": "Oops, something went wrong.",
"still_loading": "Still loading..."
"still_loading": "Still loading...",
"tag_label_programming_language": "programming"
}
12 changes: 11 additions & 1 deletion js/locale/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,15 @@
"hot_topics": "Sujets populaires",
"sites": "Sites",
"find_new_communities": "Cherchez de nouvelles communautés à rejoindre",
"no_hot_topics": "Aucun sujet populaire n'a été trouvé pour ce site."
"no_hot_topics": "Aucun sujet populaire n'a été trouvé pour ce site.",
"discover_communities": "Communautés",
"discover_pick_tag": "Qu'est-ce qui vous intéresse ?",
"discover_explore_more": "Explorer un autre sujet",
"discover_communities_section": "COMMUNAUTÉS",
"discover_topics_section": "SUJETS",
"discover_see_all_communities": "Voir toutes les communautés",
"remove_from_home_screen": "Supprimer",
"preview": "Aperçu",
"community_recent_topics": "Sujets populaires",
"tag_label_programming_language": "programmation"
}
82 changes: 49 additions & 33 deletions js/screens/CommonComponents/SiteLogo.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,27 @@ import { useContext } from 'react';
import { Image, Text, View } from 'react-native';
import { ThemeContext } from '../../ThemeContext';

const SiteLogo = props => {
const theme = useContext(ThemeContext);
export function isValidLogoUrl(url) {
return url && !url.endsWith('.webp') && !url.endsWith('.svg');
}

function hashCode(str) {
let hash = 0;
for (var i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
return hash;
function hashCode(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
return hash;
}

const SiteLogo = ({
logoImage,
title,
size = 42,
borderRadius = 10,
style,
}) => {
const theme = useContext(ThemeContext);
const fontSize = Math.round(size * 0.62);

function pickColor(str, text = false) {
const darkMode = theme.name === 'dark';
Expand All @@ -29,46 +40,51 @@ const SiteLogo = props => {
return `hsl(${hashCode(str) % 360}, ${s}%, ${l}%)`;
}

if (props.logoImage === false) {
// Generate a placeholder icon in lieu of a logo from the site's first initial character
if (logoImage === false) {
return (
<View
style={{
alignSelf: 'flex-start',
justifyContent: 'center',
alignItems: 'center',
height: 42,
width: 42,
marginTop: 2,
borderRadius: 10,
marginHorizontal: 4,
backgroundColor: pickColor(props.title),
}}
style={[
{
alignSelf: 'flex-start',
justifyContent: 'center',
alignItems: 'center',
height: size,
width: size,
marginTop: 2,
borderRadius,
marginHorizontal: 4,
backgroundColor: pickColor(title),
},
style,
]}
>
<Text
style={{
color: pickColor(props.title, true),
fontSize: 26,
color: pickColor(title, true),
fontSize,
fontWeight: '700',
}}
>
{props.title[0]}
{title[0]}
</Text>
</View>
);
}

return (
<Image
style={{
alignSelf: 'flex-start',
height: 42,
width: 42,
marginTop: 2,
borderRadius: 10,
marginHorizontal: 4,
}}
source={props.logoImage}
style={[
{
alignSelf: 'flex-start',
height: size,
width: size,
marginTop: 2,
borderRadius,
marginHorizontal: 4,
},
style,
]}
source={logoImage}
resizeMode="contain"
/>
);
Expand Down
Loading
Loading