Skip to content

Commit

Permalink
Merge pull request #254 from camarm-dev/dev
Browse files Browse the repository at this point in the history
Version 1.4.0
  • Loading branch information
camarm-dev authored Dec 30, 2024
2 parents 78e10e9 + 624ede2 commit 9f04395
Show file tree
Hide file tree
Showing 70 changed files with 501,053 additions and 500,789 deletions.
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Open Source and free alternative to Antidote dictionary.

[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)**

[//]: # ([<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;)

</div>

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

## Screenshots

| Home page | Word page |
|-------------------------------------|-----------------------------------------|
| ![homepage](.github/home.jpeg) | ![word page](.github/word.jpeg) |
| Sheets page | Settings page |
| ![sheets page](.github/sheets.jpeg) | ![settings page](.github/settings.jpeg) |
| Home page | Word page |
|----------------------------------------------------------|-------------------------------------------------------------|
| ![homepage](.github/home.jpeg) | ![word page](metadata/fr/images/phoneScreenshots/3.jpg) |
| Rimes | Settings page |
| ![rimes page](metadata/fr/images/phoneScreenshots/6.jpg) | ![settings page](metadata/fr/images/phoneScreenshots/7.jpg) |
| Examples | Corrector |
| ![examples](metadata/fr/images/phoneScreenshots/4.jpg) | ![corrector](metadata/fr/images/phoneScreenshots/5.jpg) |

2 changes: 1 addition & 1 deletion api-definition
18 changes: 18 additions & 0 deletions app/android/.idea/deploymentTargetSelector.xml

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

4 changes: 2 additions & 2 deletions app/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ android {
applicationId "dev.camarm.remede"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 126
versionName '1.4.0-beta — Phenomenal Feather, Beta'
versionCode 127
versionName '1.4.0'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
Expand Down
4 changes: 2 additions & 2 deletions app/android/app/release/output-metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 126,
"versionName": "1.4.0-beta — Phenomenal Feather, Beta",
"versionCode": 127,
"versionName": "1.4.0",
"outputFile": "app-release.apk"
}
],
Expand Down
8 changes: 6 additions & 2 deletions app/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,7 @@
android:label="@string/active_remede_label">
<intent-filter>
<action android:name="android.intent.action.PROCESS_TEXT" />

<category android:name="android.intent.category.DEFAULT" />

<data android:mimeType="text/plain" />
</intent-filter>
</activity>
Expand All @@ -87,4 +85,10 @@
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
</provider>
</application>
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT" />
<data android:mimeType="text/plain" />
</intent>
</queries>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
String definition;
try {
wordDocument = getWordDocument(word);
nature = wordDocument.getJSONArray("definitions").getJSONObject(0).getString("classe");
phoneme = wordDocument.getString("ipa");
definition = wordDocument.getJSONArray("definitions").getJSONObject(0).getJSONObject("explications").getString("1");
nature = wordDocument.getJSONArray("definitions").getJSONObject(0).getString("nature");
phoneme = wordDocument.getString("phoneme");
definition = wordDocument.getJSONArray("definitions").getJSONObject(0).getJSONArray("explanations").getString(0);
definition = definition.replaceAll("<[^>]*>", "");
if (definition.length() > 100) {
definition = definition.substring(0, 90) + "...";
Expand Down
14 changes: 14 additions & 0 deletions app/android/app/src/main/res/values-b+en+US/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="active_remede_label">Open Remède</string>
<string name="add_widget">Add widget</string>
<string name="app_widget_description">"Open Remède from your homescreen."</string>
<string name="searchbar">Searchbar</string>
<string name="wodwidget_label">"Word of day"</string>
<string name="wodwidget_description">"The word of day on your homescreen."</string>
<string name="wodwidget_word">Remède</string>
<string name="wodwidget_phoneme">/ʁəmɛd/</string>
<string name="wodwidget_desc">"Open free dictionary cross-platform software which goal is to replace the Antidote dictionary."</string>
<string name="wodwidget_nature">Proper name</string>
<string name="wodwidget_serif">""IBM Plex Serif", sans"</string>
</resources>
2 changes: 1 addition & 1 deletion app/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "remede",
"private": true,
"version": "1.4.0-beta",
"version": "1.4.0",
"type": "module",
"license": "CECILL-2.1",
"author": {
Expand Down
10 changes: 5 additions & 5 deletions app/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<ion-list>
<RemedeLogo class="ion-margin-start"/>
<ion-note>{{ $t('theDictionary') }}</ion-note>
<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>
<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>
<div class="menu-links">
<div class="start">
<ion-menu-toggle :auto-hide="false">
Expand Down Expand Up @@ -95,7 +95,7 @@ import RemedeLogo from "@/components/RemedeLogo.vue"

<script lang="ts">
import {useRouter} from "vue-router"
import {getOfflineDictionaryStatus} from "@/functions/offline"
import {getDownloadedDictionaries} from "@/functions/offline"
import { App } from "@capacitor/app"
import {defineComponent} from "vue"
import {wordExists} from "@/functions/dictionnary"
Expand All @@ -107,8 +107,8 @@ export default defineComponent({
this.path = location.pathname
})
document.body.classList.add(localStorage.getItem("userTheme") || "light")
getOfflineDictionaryStatus().then(status => {
this.downloaded = status.downloaded
getDownloadedDictionaries().then(dictionaries => {
this.downloaded = dictionaries.length > 0
})
App.getLaunchUrl().then(object => {
Expand Down Expand Up @@ -147,7 +147,7 @@ export default defineComponent({
this.$router.back()
return
}
const searchbar = (this.$refs.searchbar as any).$el
const searchbar = (this.$refs.menuSearchbar as any).$el
if (!searchbar?.focused && !["dictionnaire", "fiches", "correction", "rimes"].includes(this.$route.name as string)) {
await searchbar.setFocus()
if (!searchbar.focused) {
Expand Down
8 changes: 6 additions & 2 deletions app/src/data/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,17 @@
"downloadLongDescription": "To finish its installation, please restart the application !",
"downloadFailed": "Failed to download",
"downloadFailedDescription": "The offline dictionary cannot be downloaded: {error}",
"updateTo": "Update to",
"update": "Update",
"cannotDownload": "You cannot download the dictionary...",
"downloadingDisclaimer": "Please let this page open while the dictionary is downloading.\n\nYou must restart the application after the dictionary has been downloaded.",
"working": "Everything looks ok !",
"problem": "Problem detected...",
"workingNormally": "Everything looks ok ! You can start searching words offline !",
"problemDetected": "A problem has been detected, please reinstall the dictionary or contact the support.",
"understood": "That's ok !",
"dictionaryRevisionDownloaded": "Dictionary \"{name}\", revision \"{rev}\" downloaded. Taking {size} storage. {words} words."
"dictionaryRevisionDownloaded": "Revision \"{rev}\". {size} storage. {words} words.",
"myDictionaries": "My downloaded dictionaries",
"loading": "Loading..."
},
"sheetsPage": {
"placeholder": "Search a sheet",
Expand Down
8 changes: 6 additions & 2 deletions app/src/data/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,17 @@
"downloadLongDescription": "Pour finaliser son installation, veuillez relancer l'application !",
"downloadFailed": "Échec de téléchargement",
"downloadFailedDescription": "Le dictionnaire hors-ligne n'a pas pu être téléchargé: {error}",
"updateTo": "Mettre à jour vers",
"update": "Mettre à jour",
"cannotDownload": "Vous ne pouvez pas télécharger le dictionnaire...",
"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.",
"working": "Tout semble fonctionner !",
"problem": "Un problème a été détecté...",
"workingNormally": "Tout semble fonctionner parfaitement. Vous pouvez commencer à chercher des mots hors-ligne !",
"problemDetected": "Un problème a été détecté, veuillez réinstaller le dictionnaire ou contacter le support.",
"understood": "C'est compris !",
"dictionaryRevisionDownloaded": "Dictionnaire \"{name}\", révision \"{rev}\" téléchargé. Taille totale de {size} pour {words} mots."
"dictionaryRevisionDownloaded": "Révision \"{rev}\". {size} de stockage. {words} mots.",
"myDictionaries": "Mes dictionnaires téléchargés",
"loading": "Chargement..."
},
"sheetsPage": {
"placeholder": "Rechercher une fiche",
Expand Down
34 changes: 22 additions & 12 deletions app/src/functions/database.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {getRawDictionary} from "@/functions/offline"
import {getDownloadedDictionaries, getRawDictionary} from "@/functions/offline"
import initSqlJS, {Database} from "sql.js"
import {toastController} from "@ionic/vue"
import {RemedeDictionaryOption} from "@/functions/types/apiResponses"

async function openDatabase() {
async function openDatabase(dictionary: RemedeDictionaryOption) {
try {
const SQL = await initSqlJS({
locateFile: () => "/sql-wasm.wasm"
})
const raw = await getRawDictionary()
const raw = await getRawDictionary(dictionary)
return new SQL.Database(raw)
} catch (e) {
const message = await toastController.create({
Expand All @@ -25,14 +26,23 @@ class RemedeDatabase {

private db?: Database

constructor() {
this.getDatabase().then(() => {
console.log("Database loaded !")
})
constructor(dictionary?: RemedeDictionaryOption) {
if (dictionary) {
this.getDatabase(dictionary).then(() => {
console.log(`[Dictionary] Database ${dictionary?.slug}.db loaded !`)
})
} else {
getDownloadedDictionaries().then(downloadedDictionaries => {
dictionary = downloadedDictionaries.find(downloadedDictionary => downloadedDictionary.favorite) || downloadedDictionaries[0]
this.getDatabase(dictionary).then(() => {
console.log(`[Dictionary] Database ${dictionary?.slug}.db loaded !`)
})
})
}
}

private async getDatabase() {
this.db = await openDatabase()
private async getDatabase(dictionary: RemedeDictionaryOption) {
this.db = await openDatabase(dictionary)
}

async getWord(word: string) {
Expand Down Expand Up @@ -67,7 +77,7 @@ class RemedeDatabase {
}

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

Expand All @@ -91,7 +101,7 @@ class RemedeDatabase {

let natureFilter = `(${nature.length === 0}`
for (const string of nature) {
natureFilter += ` OR nature LIKE '%${string}:%' OR nature LIKE '%${string},%'`
natureFilter += ` OR nature LIKE '%${string}%' OR nature LIKE '%${string},%'`
}
natureFilter += ")"

Expand All @@ -101,7 +111,7 @@ class RemedeDatabase {
AND (feminine OR ${!feminine})
AND ${qualityFilter}
AND ${natureFilter})
ORDER BY word ASC LIMIT 50 OFFSET ${page * 50}`
ORDER BY lower(word) ASC LIMIT 50 OFFSET ${page * 50}`
return await this.rawQuery(query)
}

Expand Down
54 changes: 42 additions & 12 deletions app/src/functions/dictionnary.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,59 @@
import {getOfflineDictionaryStatus} from "@/functions/offline"
import {getDownloadedDictionaries} from "@/functions/offline"
import {RemedeDatabase} from "@/functions/database"
import {FilledRemedeWordDocument, RemedeSource, RemedeWordDocument} from "@/functions/types/remede"
import {InformationsResponse, RemedeDictionaryOption} from "@/functions/types/apiResponses"

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

async function useApi() {
return !(await getOfflineDictionaryStatus()).downloaded
return (await getDownloadedDictionaries()).length == 0
}

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

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

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

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

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

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

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

async function getRandomWordFromDatabase() {
return await database?.getRandomWord() as string
}

async function doesWordExistsWithAPI(word: string) {
return (await fetch(`https://api-remede.camarm.fr/word/${word}`).then(resp => resp.json()).catch(() => { return { message: "Mot non trouvé" } })).message != "Mot non trouvé"
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é"
}

async function getWordsWithPhonemeWithAPI(phoneme: string) {
return await fetch(`https://api-remede.camarm.fr/phoneme/${phoneme}`).then(resp => resp.json())
return await fetch(`https://api-remede.camarm.fr/phoneme/${phoneme}?database=${databaseSlug}`).then(resp => resp.json())
}

async function getAvailableDictionariesWithAPI() {
const response = await fetch("https://api-remede.camarm.fr").then(resp => resp.json()) as InformationsResponse
return Object.values(response.dictionaries)
}

async function doesWordExistsWithDatabase(word: string) {
Expand Down Expand Up @@ -99,7 +105,7 @@ async function getRandomWord() {

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

const database = await useApi() ? null: new RemedeDatabase()
async function getAvailableDictionaries(): Promise<RemedeDictionaryOption[]> {
if (await useApi()) {
return await getAvailableDictionariesWithAPI()
}
return await getDownloadedDictionaries()
}

async function getFavoriteDictionary(dictionaries: RemedeDictionaryOption[]): Promise<RemedeDictionaryOption> {
if (await useApi()) {
return dictionaries[0]
}
return (await getDownloadedDictionaries()).find(downloadedDictionary => downloadedDictionary.favorite) || dictionaries[0]
}

let database = await useApi() ? null: new RemedeDatabase()
let databaseSlug = "remede"

async function setDictionary(dictionary: RemedeDictionaryOption) {
console.log(`[Dictionary] Setting dictionary to ${dictionary.name} (${dictionary.slug})`)
database = await useApi() ? null: new RemedeDatabase(dictionary)
databaseSlug = dictionary.slug
}

export {
getWordDocument,
Expand All @@ -159,5 +186,8 @@ export {
wordExists,
getWordRimes,
getRimesAutocomplete,
getWordsWithPhoneme
getWordsWithPhoneme,
getAvailableDictionaries,
getFavoriteDictionary,
setDictionary
}
Loading

0 comments on commit 9f04395

Please sign in to comment.