Skip to content

Commit 6697ab4

Browse files
Merge pull request #375 from AndreWohnsland/dev
Add addon update option
2 parents bc43179 + 218da5e commit 6697ab4

File tree

6 files changed

+78
-21
lines changed

6 files changed

+78
-21
lines changed

src/api/routers/options.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,18 @@ async def delete_addon(addon: AddonData) -> ApiMessage:
272272
return ApiMessage(message=f"Addon {addon.name} removed")
273273

274274

275+
@protected_router.post("/addon/update", summary="Update addon")
276+
async def update_addon(addon: AddonData) -> ApiMessage:
277+
possible_addons = ADDONS.get_addon_data()
278+
matched_addon = next((a for a in possible_addons if a.name == addon.name and a.official), None)
279+
if not matched_addon:
280+
raise HTTPException(400, detail="Addon is not official or not found")
281+
if matched_addon.can_update:
282+
ADDONS.reload_addon(matched_addon)
283+
return ApiMessage(message=f"Addon {addon.name} updated")
284+
raise HTTPException(400, detail="Addon cannot be updated")
285+
286+
275287
@protected_router.get("/connection", summary="Check internet connection")
276288
async def check_internet_connection() -> dict[str, Union[str, bool]]: # noqa: UP007
277289
is_connected = has_connection()

src/ui/setup_addon_manager.py

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -43,28 +43,43 @@ def _fill_addon_list(self) -> None:
4343
if widget:
4444
widget.deleteLater()
4545

46-
for i, addon in enumerate(self._addon_information):
47-
if addon.installed and addon.official and not addon.is_installable:
48-
btn = create_button("Remove", font_size=16, max_w=150, css_class="btn-inverted destructive")
49-
btn.clicked.connect(lambda _, a=addon, b=btn, c=i: self._remove_addon(a, b, c))
50-
elif addon.official and addon.is_installable:
51-
btn = create_button("Install", font_size=16, max_w=150, css_class="btn-inverted")
52-
btn.clicked.connect(lambda _, a=addon, b=btn, c=i: self._install_addon(a, b, c))
53-
else:
54-
if addon.disabled:
55-
text = "Disabled"
56-
elif not addon.official:
57-
text = "Unofficial"
58-
else:
59-
text = f"needs {addon.minimal_version}+"
60-
btn = create_button(text, font_size=16, max_w=150, css_class="neutral btn-inverted")
61-
btn.setEnabled(False)
46+
current_grid_index = 0
6247

63-
self.gridLayout_2.addWidget(btn, i, 0)
48+
for addon in sorted(
49+
self._addon_information,
50+
key=lambda x: (x.official, x.installed, x.is_installable, x.name),
51+
reverse=True,
52+
):
53+
btn = self._create_addon_button(current_grid_index, addon)
54+
self.gridLayout_2.addWidget(btn, current_grid_index, 0)
6455
content = f"{addon.name} ({addon.file_name})\n{addon.description}"
6556
label = create_label(content, SMALL_FONT)
6657
label.setWordWrap(True)
67-
self.gridLayout_2.addWidget(label, i, 1)
58+
self.gridLayout_2.addWidget(label, current_grid_index, 1)
59+
current_grid_index += 1
60+
if addon.can_update:
61+
btn = create_button(f"Update ({addon.version})", font_size=16, css_class="btn-inverted")
62+
btn.clicked.connect(lambda _, a=addon, b=btn, c=current_grid_index: self._update_addon(a, b, c))
63+
self.gridLayout_2.addWidget(btn, current_grid_index, 1)
64+
current_grid_index += 1
65+
66+
def _create_addon_button(self, current_grid_index: int, addon: AddonData) -> QPushButton:
67+
if addon.installed and addon.official:
68+
btn = create_button("Remove", font_size=16, max_w=150, css_class="btn-inverted destructive")
69+
btn.clicked.connect(lambda _, a=addon, b=btn, c=current_grid_index: self._remove_addon(a, b, c))
70+
elif addon.official and addon.is_installable:
71+
btn = create_button("Install", font_size=16, max_w=150, css_class="btn-inverted")
72+
btn.clicked.connect(lambda _, a=addon, b=btn, c=current_grid_index: self._install_addon(a, b, c))
73+
else:
74+
if addon.disabled:
75+
text = "Disabled"
76+
elif not addon.official:
77+
text = "Unofficial"
78+
else:
79+
text = f"needs {addon.minimal_version}+"
80+
btn = create_button(text, font_size=16, max_w=150, css_class="neutral btn-inverted")
81+
btn.setEnabled(False)
82+
return btn
6883

6984
def _install_addon(self, addon: AddonData, btn: QPushButton, pos: int) -> None:
7085
"""Try to install addon, log if req is not ok or no connection."""
@@ -88,3 +103,12 @@ def _remove_addon(self, addon: AddonData, btn: QPushButton, pos: int) -> None:
88103
btn = create_button("Install", font_size=16, max_w=200, css_class="btn-inverted")
89104
btn.clicked.connect(lambda _, a=addon, b=btn, c=pos: self._install_addon(a, b, c))
90105
self.gridLayout_2.addWidget(btn, pos, 0)
106+
107+
def _update_addon(self, addon: AddonData, btn: QPushButton, pos: int) -> None:
108+
"""Try to update addon, log if req is not ok or no connection."""
109+
try:
110+
ADDONS.reload_addon(addon)
111+
DIALOG_HANDLER.standard_box("Addon updated successfully", "Success")
112+
btn.deleteLater()
113+
except CouldNotInstallAddonError as e:
114+
_logger.log_event("ERROR", str(e))

web_client/src/api/options.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ export const deleteAddon = async (addon: AddonData): Promise<{ message: string }
142142
.then((res) => res.data);
143143
};
144144

145+
export const updateAddon = async (addon: AddonData): Promise<{ message: string }> => {
146+
return axiosInstance.post<{ message: string }>(`${optionsUrl}/addon/update`, addon).then((res) => res.data);
147+
};
148+
145149
// Authentication
146150
export const validateMakerPassword = async (password: number): Promise<{ message: string }> => {
147151
return axiosInstance

web_client/src/components/options/AddonManager.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import { useTranslation } from 'react-i18next';
33
import { FaPlus, FaTrashAlt } from 'react-icons/fa';
4-
import { addAddon, deleteAddon, useAddonData } from '../../api/options';
4+
import { addAddon, deleteAddon, updateAddon, useAddonData } from '../../api/options';
55
import { AddonData } from '../../types/models';
66
import { confirmAndExecute, executeAndShow } from '../../utils';
77
import ErrorComponent from '../common/ErrorComponent';
@@ -45,6 +45,14 @@ const AddonManager: React.FC = () => {
4545
});
4646
};
4747

48+
const handleUpdate = async (addon: AddonData) => {
49+
confirmAndExecute(t('addons.updateTheAddon', { addon: addon.name }), () => updateAddon(addon)).then((success) => {
50+
if (success) {
51+
refetch();
52+
}
53+
});
54+
};
55+
4856
const createAddonButton = (addon: AddonData) => {
4957
if (addon.is_installable && addon.official && !addon.installed) {
5058
return (
@@ -89,6 +97,11 @@ const AddonManager: React.FC = () => {
8997
{createAddonButton(addon)}
9098
</div>
9199
<p>{addon.description}</p>
100+
{addon.can_update && (
101+
<button onClick={() => handleUpdate(addon)} className='button-primary-filled p-2 px-4 mt-6 w-full'>
102+
{t('addons.update', { version: addon.version })}
103+
</button>
104+
)}
92105
</div>
93106
))}
94107
</div>

web_client/src/locales/de/translation.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@
114114
"minVersionNotMet": "Braucht Version: {{version}}",
115115
"cannotBeInstalled": "Kann nicht installiert werden",
116116
"notOfficial": "Nicht Offiziell",
117-
"deleteTheAddon": "Möchtest du das Addon '{{addon}}' löschen?"
117+
"deleteTheAddon": "Möchtest du das Addon '{{addon}}' löschen?",
118+
"updateTheAddon": "Möchtest du das Addon '{{addon}}' updaten?",
119+
"update": "Update ({{version}})"
118120
},
119121
"wifi": {
120122
"setupWifi": "WLAN einrichten",

web_client/src/locales/en/translation.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@
114114
"minVersionNotMet": "Needs Version: {{version}}",
115115
"cannotBeInstalled": "Cannot be Installed",
116116
"notOfficial": "Not Official",
117-
"deleteTheAddon": "Do you want to delete the addon '{{addon}}'?"
117+
"deleteTheAddon": "Do you want to delete the addon '{{addon}}'?",
118+
"updateTheAddon": "Do you want to update the addon '{{addon}}'?",
119+
"update": "Update ({{version}})"
118120
},
119121
"wifi": {
120122
"setupWifi": "Set Up WiFi",

0 commit comments

Comments
 (0)