Skip to content

Commit 9f04395

Browse files
authored
Merge pull request #254 from camarm-dev/dev
Version 1.4.0
2 parents 78e10e9 + 624ede2 commit 9f04395

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+501053
-500789
lines changed

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Open Source and free alternative to Antidote dictionary.
1010

1111
[Data credits](https://docs.remede.camarm.fr/docs/database/credits)[License](https://github.com/camarm-dev/remede/blob/main/LICENSE)[Website](https://remede.camarm.fr)**[Download](https://remede.camarm.fr/download)****[API](https://api-remede.camarm.fr/docs)**
1212

13+
[//]: # ([<img src="https://f-droid.org/badge/get-it-on.png" alt="Get it on F-Droid" height="70">]&#40;https://f-droid.org/packages/dev.camarm.remede&#41;)
14+
1315
</div>
1416

1517
## Breaking changes with Remède 1.4.0
@@ -66,9 +68,11 @@ La documentation est disponible sur [docs.remede.camarm.fr](https://docs.remede.
6668

6769
## Screenshots
6870

69-
| Home page | Word page |
70-
|-------------------------------------|-----------------------------------------|
71-
| ![homepage](.github/home.jpeg) | ![word page](.github/word.jpeg) |
72-
| Sheets page | Settings page |
73-
| ![sheets page](.github/sheets.jpeg) | ![settings page](.github/settings.jpeg) |
71+
| Home page | Word page |
72+
|----------------------------------------------------------|-------------------------------------------------------------|
73+
| ![homepage](.github/home.jpeg) | ![word page](metadata/fr/images/phoneScreenshots/3.jpg) |
74+
| Rimes | Settings page |
75+
| ![rimes page](metadata/fr/images/phoneScreenshots/6.jpg) | ![settings page](metadata/fr/images/phoneScreenshots/7.jpg) |
76+
| Examples | Corrector |
77+
| ![examples](metadata/fr/images/phoneScreenshots/4.jpg) | ![corrector](metadata/fr/images/phoneScreenshots/5.jpg) |
7478

app/android/.idea/deploymentTargetSelector.xml

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ android {
1111
applicationId "dev.camarm.remede"
1212
minSdkVersion rootProject.ext.minSdkVersion
1313
targetSdkVersion rootProject.ext.targetSdkVersion
14-
versionCode 126
15-
versionName '1.4.0-beta — Phenomenal Feather, Beta'
14+
versionCode 127
15+
versionName '1.4.0'
1616
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1717
aaptOptions {
1818
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.

app/android/app/release/output-metadata.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
"type": "SINGLE",
1212
"filters": [],
1313
"attributes": [],
14-
"versionCode": 126,
15-
"versionName": "1.4.0-beta — Phenomenal Feather, Beta",
14+
"versionCode": 127,
15+
"versionName": "1.4.0",
1616
"outputFile": "app-release.apk"
1717
}
1818
],

app/android/app/src/main/AndroidManifest.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,7 @@
7272
android:label="@string/active_remede_label">
7373
<intent-filter>
7474
<action android:name="android.intent.action.PROCESS_TEXT" />
75-
7675
<category android:name="android.intent.category.DEFAULT" />
77-
7876
<data android:mimeType="text/plain" />
7977
</intent-filter>
8078
</activity>
@@ -87,4 +85,10 @@
8785
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
8886
</provider>
8987
</application>
88+
<queries>
89+
<intent>
90+
<action android:name="android.intent.action.PROCESS_TEXT" />
91+
<data android:mimeType="text/plain" />
92+
</intent>
93+
</queries>
9094
</manifest>

app/android/app/src/main/java/dev/camarm/remede/RemedeWordOfDayWidget.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
8484
String definition;
8585
try {
8686
wordDocument = getWordDocument(word);
87-
nature = wordDocument.getJSONArray("definitions").getJSONObject(0).getString("classe");
88-
phoneme = wordDocument.getString("ipa");
89-
definition = wordDocument.getJSONArray("definitions").getJSONObject(0).getJSONObject("explications").getString("1");
87+
nature = wordDocument.getJSONArray("definitions").getJSONObject(0).getString("nature");
88+
phoneme = wordDocument.getString("phoneme");
89+
definition = wordDocument.getJSONArray("definitions").getJSONObject(0).getJSONArray("explanations").getString(0);
9090
definition = definition.replaceAll("<[^>]*>", "");
9191
if (definition.length() > 100) {
9292
definition = definition.substring(0, 90) + "...";
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version='1.0' encoding='utf-8'?>
2+
<resources>
3+
<string name="active_remede_label">Open Remède</string>
4+
<string name="add_widget">Add widget</string>
5+
<string name="app_widget_description">"Open Remède from your homescreen."</string>
6+
<string name="searchbar">Searchbar</string>
7+
<string name="wodwidget_label">"Word of day"</string>
8+
<string name="wodwidget_description">"The word of day on your homescreen."</string>
9+
<string name="wodwidget_word">Remède</string>
10+
<string name="wodwidget_phoneme">/ʁəmɛd/</string>
11+
<string name="wodwidget_desc">"Open free dictionary cross-platform software which goal is to replace the Antidote dictionary."</string>
12+
<string name="wodwidget_nature">Proper name</string>
13+
<string name="wodwidget_serif">""IBM Plex Serif", sans"</string>
14+
</resources>

app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "remede",
33
"private": true,
4-
"version": "1.4.0-beta",
4+
"version": "1.4.0",
55
"type": "module",
66
"license": "CECILL-2.1",
77
"author": {

app/src/App.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<ion-list>
88
<RemedeLogo class="ion-margin-start"/>
99
<ion-note>{{ $t('theDictionary') }}</ion-note>
10-
<ion-searchbar :value="query" @ionChange="query = $event.detail.value as string" ref="searchbar" @keydown.enter="handleFastSearch($event.target.value)" :class="`hidden-mobile ${isPage('/dictionnaire') ? 'hidden': ''}`" :placeholder="$t('home.searchWord')"></ion-searchbar>
10+
<ion-searchbar :value="query" @ionChange="query = $event.detail.value as string" ref="menuSearchbar" @keydown.enter="handleFastSearch($event.target.value)" :class="`hidden-mobile ${isPage('/dictionnaire') ? 'hidden': ''}`" :placeholder="$t('home.searchWord')"></ion-searchbar>
1111
<div class="menu-links">
1212
<div class="start">
1313
<ion-menu-toggle :auto-hide="false">
@@ -95,7 +95,7 @@ import RemedeLogo from "@/components/RemedeLogo.vue"
9595

9696
<script lang="ts">
9797
import {useRouter} from "vue-router"
98-
import {getOfflineDictionaryStatus} from "@/functions/offline"
98+
import {getDownloadedDictionaries} from "@/functions/offline"
9999
import { App } from "@capacitor/app"
100100
import {defineComponent} from "vue"
101101
import {wordExists} from "@/functions/dictionnary"
@@ -107,8 +107,8 @@ export default defineComponent({
107107
this.path = location.pathname
108108
})
109109
document.body.classList.add(localStorage.getItem("userTheme") || "light")
110-
getOfflineDictionaryStatus().then(status => {
111-
this.downloaded = status.downloaded
110+
getDownloadedDictionaries().then(dictionaries => {
111+
this.downloaded = dictionaries.length > 0
112112
})
113113
114114
App.getLaunchUrl().then(object => {
@@ -147,7 +147,7 @@ export default defineComponent({
147147
this.$router.back()
148148
return
149149
}
150-
const searchbar = (this.$refs.searchbar as any).$el
150+
const searchbar = (this.$refs.menuSearchbar as any).$el
151151
if (!searchbar?.focused && !["dictionnaire", "fiches", "correction", "rimes"].includes(this.$route.name as string)) {
152152
await searchbar.setFocus()
153153
if (!searchbar.focused) {

app/src/data/translations/en.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,17 @@
159159
"downloadLongDescription": "To finish its installation, please restart the application !",
160160
"downloadFailed": "Failed to download",
161161
"downloadFailedDescription": "The offline dictionary cannot be downloaded: {error}",
162-
"updateTo": "Update to",
162+
"update": "Update",
163163
"cannotDownload": "You cannot download the dictionary...",
164164
"downloadingDisclaimer": "Please let this page open while the dictionary is downloading.\n\nYou must restart the application after the dictionary has been downloaded.",
165+
"working": "Everything looks ok !",
166+
"problem": "Problem detected...",
165167
"workingNormally": "Everything looks ok ! You can start searching words offline !",
166168
"problemDetected": "A problem has been detected, please reinstall the dictionary or contact the support.",
167169
"understood": "That's ok !",
168-
"dictionaryRevisionDownloaded": "Dictionary \"{name}\", revision \"{rev}\" downloaded. Taking {size} storage. {words} words."
170+
"dictionaryRevisionDownloaded": "Revision \"{rev}\". {size} storage. {words} words.",
171+
"myDictionaries": "My downloaded dictionaries",
172+
"loading": "Loading..."
169173
},
170174
"sheetsPage": {
171175
"placeholder": "Search a sheet",

app/src/data/translations/fr.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,17 @@
159159
"downloadLongDescription": "Pour finaliser son installation, veuillez relancer l'application !",
160160
"downloadFailed": "Échec de téléchargement",
161161
"downloadFailedDescription": "Le dictionnaire hors-ligne n'a pas pu être téléchargé: {error}",
162-
"updateTo": "Mettre à jour vers",
162+
"update": "Mettre à jour",
163163
"cannotDownload": "Vous ne pouvez pas télécharger le dictionnaire...",
164164
"downloadingDisclaimer": "Veuillez ne pas quitter cette page pendant le téléchargement.\n\nIl est conseillé de redémarrer l'application après le téléchargement.",
165+
"working": "Tout semble fonctionner !",
166+
"problem": "Un problème a été détecté...",
165167
"workingNormally": "Tout semble fonctionner parfaitement. Vous pouvez commencer à chercher des mots hors-ligne !",
166168
"problemDetected": "Un problème a été détecté, veuillez réinstaller le dictionnaire ou contacter le support.",
167169
"understood": "C'est compris !",
168-
"dictionaryRevisionDownloaded": "Dictionnaire \"{name}\", révision \"{rev}\" téléchargé. Taille totale de {size} pour {words} mots."
170+
"dictionaryRevisionDownloaded": "Révision \"{rev}\". {size} de stockage. {words} mots.",
171+
"myDictionaries": "Mes dictionnaires téléchargés",
172+
"loading": "Chargement..."
169173
},
170174
"sheetsPage": {
171175
"placeholder": "Rechercher une fiche",

app/src/functions/database.ts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
import {getRawDictionary} from "@/functions/offline"
1+
import {getDownloadedDictionaries, getRawDictionary} from "@/functions/offline"
22
import initSqlJS, {Database} from "sql.js"
33
import {toastController} from "@ionic/vue"
4+
import {RemedeDictionaryOption} from "@/functions/types/apiResponses"
45

5-
async function openDatabase() {
6+
async function openDatabase(dictionary: RemedeDictionaryOption) {
67
try {
78
const SQL = await initSqlJS({
89
locateFile: () => "/sql-wasm.wasm"
910
})
10-
const raw = await getRawDictionary()
11+
const raw = await getRawDictionary(dictionary)
1112
return new SQL.Database(raw)
1213
} catch (e) {
1314
const message = await toastController.create({
@@ -25,14 +26,23 @@ class RemedeDatabase {
2526

2627
private db?: Database
2728

28-
constructor() {
29-
this.getDatabase().then(() => {
30-
console.log("Database loaded !")
31-
})
29+
constructor(dictionary?: RemedeDictionaryOption) {
30+
if (dictionary) {
31+
this.getDatabase(dictionary).then(() => {
32+
console.log(`[Dictionary] Database ${dictionary?.slug}.db loaded !`)
33+
})
34+
} else {
35+
getDownloadedDictionaries().then(downloadedDictionaries => {
36+
dictionary = downloadedDictionaries.find(downloadedDictionary => downloadedDictionary.favorite) || downloadedDictionaries[0]
37+
this.getDatabase(dictionary).then(() => {
38+
console.log(`[Dictionary] Database ${dictionary?.slug}.db loaded !`)
39+
})
40+
})
41+
}
3242
}
3343

34-
private async getDatabase() {
35-
this.db = await openDatabase()
44+
private async getDatabase(dictionary: RemedeDictionaryOption) {
45+
this.db = await openDatabase(dictionary)
3646
}
3747

3848
async getWord(word: string) {
@@ -67,7 +77,7 @@ class RemedeDatabase {
6777
}
6878

6979
async getRimesAutocomplete(query: string) {
70-
const statement = `SELECT word FROM dictionary WHERE word LIKE '${query}%' OR word = '${query}' ORDER BY word ASC LIMIT 5`
80+
const statement = `SELECT word FROM dictionary WHERE word LIKE '${query}%' OR word = '${query}' ORDER BY lower(word) ASC LIMIT 5`
7181
return await this.query(statement) as any as Promise<string[]>
7282
}
7383

@@ -91,7 +101,7 @@ class RemedeDatabase {
91101

92102
let natureFilter = `(${nature.length === 0}`
93103
for (const string of nature) {
94-
natureFilter += ` OR nature LIKE '%${string}:%' OR nature LIKE '%${string},%'`
104+
natureFilter += ` OR nature LIKE '%${string}%' OR nature LIKE '%${string},%'`
95105
}
96106
natureFilter += ")"
97107

@@ -101,7 +111,7 @@ class RemedeDatabase {
101111
AND (feminine OR ${!feminine})
102112
AND ${qualityFilter}
103113
AND ${natureFilter})
104-
ORDER BY word ASC LIMIT 50 OFFSET ${page * 50}`
114+
ORDER BY lower(word) ASC LIMIT 50 OFFSET ${page * 50}`
105115
return await this.rawQuery(query)
106116
}
107117

app/src/functions/dictionnary.ts

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,59 @@
1-
import {getOfflineDictionaryStatus} from "@/functions/offline"
1+
import {getDownloadedDictionaries} from "@/functions/offline"
22
import {RemedeDatabase} from "@/functions/database"
33
import {FilledRemedeWordDocument, RemedeSource, RemedeWordDocument} from "@/functions/types/remede"
4+
import {InformationsResponse, RemedeDictionaryOption} from "@/functions/types/apiResponses"
45

56
function removeAccents(value: string) {
6-
return value.normalize("NFD").replace(/\p{Diacritic}/gu, "").replaceAll("-", " ").replaceAll("'", " ")
7+
return value.normalize("NFD").replace(/\p{Diacritic}/gu, "").replaceAll("-", " ").replaceAll("'", " ").trim()
78
}
89

910
async function useApi() {
10-
return !(await getOfflineDictionaryStatus()).downloaded
11+
return (await getDownloadedDictionaries()).length == 0
1112
}
1213

1314
async function getAutocompleteWithAPI(word: string) {
14-
return await fetch(`https://api-remede.camarm.fr/autocomplete/${word}`).then(resp => resp.json())
15+
return await fetch(`https://api-remede.camarm.fr/autocomplete/${word}?database=${databaseSlug}`).then(resp => resp.json())
1516
}
1617

1718
async function getAutocompleteFromDatabase(word: string) {
1819
return await database?.getAutocomplete(removeAccents(word)) as any[]
1920
}
2021

2122
async function getSearchResultsWithAPI(query: string, page: number) {
22-
return await fetch(`https://api-remede.camarm.fr/search/${query}?page=${page}`).then(resp => resp.json())
23+
return await fetch(`https://api-remede.camarm.fr/search/${query}?page=${page}&database=${databaseSlug}`).then(resp => resp.json())
2324
}
2425

2526
async function getSearchResultsFromDatabase(query: string, page: number) {
2627
return await database?.search(removeAccents(query), page) as any[]
2728
}
2829

2930
async function getWordWithAPI(word: string) {
30-
return await fetch(`https://api-remede.camarm.fr/word/${word}`).then(resp => resp.json())
31+
return await fetch(`https://api-remede.camarm.fr/word/${word}?database=${databaseSlug}`).then(resp => resp.json())
3132
}
3233

3334
async function getWordFromDatabase(word: string) {
3435
return await database?.getWord(word) as any
3536
}
3637

3738
async function getRandomWordWithAPI() {
38-
return await fetch("https://api-remede.camarm.fr/random").then(resp => resp.json())
39+
return await fetch(`https://api-remede.camarm.fr/random?database=${databaseSlug}`).then(resp => resp.json())
3940
}
4041

4142
async function getRandomWordFromDatabase() {
4243
return await database?.getRandomWord() as string
4344
}
4445

4546
async function doesWordExistsWithAPI(word: string) {
46-
return (await fetch(`https://api-remede.camarm.fr/word/${word}`).then(resp => resp.json()).catch(() => { return { message: "Mot non trouvé" } })).message != "Mot non trouvé"
47+
return (await fetch(`https://api-remede.camarm.fr/word/${word}?database=${databaseSlug}`).then(resp => resp.json()).catch(() => { return { message: "Mot non trouvé" } })).message != "Mot non trouvé"
4748
}
4849

4950
async function getWordsWithPhonemeWithAPI(phoneme: string) {
50-
return await fetch(`https://api-remede.camarm.fr/phoneme/${phoneme}`).then(resp => resp.json())
51+
return await fetch(`https://api-remede.camarm.fr/phoneme/${phoneme}?database=${databaseSlug}`).then(resp => resp.json())
52+
}
53+
54+
async function getAvailableDictionariesWithAPI() {
55+
const response = await fetch("https://api-remede.camarm.fr").then(resp => resp.json()) as InformationsResponse
56+
return Object.values(response.dictionaries)
5157
}
5258

5359
async function doesWordExistsWithDatabase(word: string) {
@@ -99,7 +105,7 @@ async function getRandomWord() {
99105

100106
async function getTodayWord() {
101107
try {
102-
return await fetch("https://api-remede.camarm.fr/word-of-day").then(resp => resp.json())
108+
return await fetch(`https://api-remede.camarm.fr/word-of-day?database=${databaseSlug}`).then(resp => resp.json())
103109
} catch (e) {
104110
return ""
105111
}
@@ -148,7 +154,28 @@ async function getSource(source: string | RemedeSource): Promise<RemedeSource> {
148154
return await database?.getSource(source as string) as any as Promise<RemedeSource>
149155
}
150156

151-
const database = await useApi() ? null: new RemedeDatabase()
157+
async function getAvailableDictionaries(): Promise<RemedeDictionaryOption[]> {
158+
if (await useApi()) {
159+
return await getAvailableDictionariesWithAPI()
160+
}
161+
return await getDownloadedDictionaries()
162+
}
163+
164+
async function getFavoriteDictionary(dictionaries: RemedeDictionaryOption[]): Promise<RemedeDictionaryOption> {
165+
if (await useApi()) {
166+
return dictionaries[0]
167+
}
168+
return (await getDownloadedDictionaries()).find(downloadedDictionary => downloadedDictionary.favorite) || dictionaries[0]
169+
}
170+
171+
let database = await useApi() ? null: new RemedeDatabase()
172+
let databaseSlug = "remede"
173+
174+
async function setDictionary(dictionary: RemedeDictionaryOption) {
175+
console.log(`[Dictionary] Setting dictionary to ${dictionary.name} (${dictionary.slug})`)
176+
database = await useApi() ? null: new RemedeDatabase(dictionary)
177+
databaseSlug = dictionary.slug
178+
}
152179

153180
export {
154181
getWordDocument,
@@ -159,5 +186,8 @@ export {
159186
wordExists,
160187
getWordRimes,
161188
getRimesAutocomplete,
162-
getWordsWithPhoneme
189+
getWordsWithPhoneme,
190+
getAvailableDictionaries,
191+
getFavoriteDictionary,
192+
setDictionary
163193
}

0 commit comments

Comments
 (0)