Skip to content

Commit e542b6d

Browse files
committed
Add support for installing plugin-hub plugins via website
This works only for logged in users as it is simply changing the config. Signed-off-by: Tomas Slusny <slusnucky@gmail.com>
1 parent d551092 commit e542b6d

File tree

4 files changed

+126
-10
lines changed

4 files changed

+126
-10
lines changed

src/components/external-plugin.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ const ExternalPlugin = ({
99
support,
1010
imageUrl,
1111
installed,
12-
count
12+
internalName,
13+
count,
14+
update,
15+
showInstall
1316
}) => (
1417
<div class="col-md-4 col-sm-6 col-xs-12 mb-2">
1518
<div class="card">
@@ -45,7 +48,22 @@ const ExternalPlugin = ({
4548
{numberWithCommas(count)}{' '}
4649
{count > 1 ? 'active installs' : 'active install'}
4750
</span>{' '}
48-
{installed && <span class="badge badge-success">installed</span>}
51+
{showInstall &&
52+
(installed ? (
53+
<button
54+
class="badge badge-danger btn"
55+
onClick={() => update(installed, internalName)}
56+
>
57+
uninstall
58+
</button>
59+
) : (
60+
<button
61+
class="badge badge-success btn"
62+
onClick={() => update(installed, internalName)}
63+
>
64+
install
65+
</button>
66+
))}
4967
</p>
5068
)}
5169
<p class="card-text">

src/modules/config.js

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@ const configNameFilters = [
1515
]
1616

1717
// Actions
18-
export const { fetchConfig, setConfig, changeAccount } = createActions(
18+
export const {
19+
fetchConfig,
20+
updateConfig,
21+
setConfig,
22+
addModifiedKey,
23+
changeAccount
24+
} = createActions(
1925
{
2026
FETCH_CONFIG: () => async (dispatch, getState) => {
2127
const version = getLatestRelease(getState())
@@ -51,9 +57,37 @@ export const { fetchConfig, setConfig, changeAccount } = createActions(
5157
}
5258

5359
return config
60+
},
61+
UPDATE_CONFIG: (key, value) => async (dispatch, getState) => {
62+
const version = getLatestRelease(getState())
63+
const uuid = getState().account.uuid
64+
65+
if (!uuid) {
66+
return {}
67+
}
68+
69+
if (value.length > 0) {
70+
await runeliteApi(`runelite-${version}/config/${key}`, {
71+
method: 'PUT',
72+
headers: {
73+
'RUNELITE-AUTH': uuid
74+
},
75+
body: value
76+
})
77+
} else {
78+
await runeliteApi(`runelite-${version}/config/${key}`, {
79+
method: 'DELETE',
80+
headers: {
81+
'RUNELITE-AUTH': uuid
82+
}
83+
})
84+
}
85+
86+
dispatch(addModifiedKey(key))
5487
}
5588
},
5689
'SET_CONFIG',
90+
'ADD_MODIFIED_KEY',
5791
'CHANGE_ACCOUNT'
5892
)
5993

@@ -67,17 +101,23 @@ export default handleActions(
67101
[changeAccount]: (state, { payload }) => ({
68102
...state,
69103
selectedAccount: payload
104+
}),
105+
[addModifiedKey]: (state, { payload }) => ({
106+
...state,
107+
modifiedKeys: [...new Set(state.modifiedKeys.concat([payload]))]
70108
})
71109
},
72110
{
73111
config: {},
112+
modifiedKeys: [],
74113
selectedAccount: ''
75114
}
76115
)
77116

78117
// Selectors
79118
export const getConfig = state => state.config.config
80119
export const getSelectedAccount = state => state.config.selectedAccount
120+
export const getModifiedKeys = state => state.config.modifiedKeys
81121

82122
export const getAccounts = createSelector(getConfig, config => {
83123
const names = new Set()

src/routes/plugin-hub.js

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,15 @@ import {
1717
setPluginSorting
1818
} from '../modules/plugin-hub'
1919
import SearchBar from '../components/search-bar'
20-
import { fetchConfig } from '../modules/config'
20+
import {
21+
fetchConfig,
22+
getExternalPlugins,
23+
getModifiedKeys,
24+
updateConfig
25+
} from '../modules/config'
2126
import Choice from '../components/choice'
2227
import { numberWithCommas } from '../util'
28+
import { isLoggedIn } from '../modules/account'
2329

2430
const description =
2531
'The Plugin Hub is a repository of plugins that are created and ' +
@@ -33,21 +39,45 @@ const handleChange = (event, setPluginFilter) =>
3339
name: event.target.value
3440
})
3541

42+
const handleUpdate = (updateConfig, fetchConfig, externalPlugins) => async (
43+
installed,
44+
pluginName
45+
) => {
46+
if (installed) {
47+
externalPlugins = externalPlugins.filter(i => i !== pluginName)
48+
} else {
49+
externalPlugins.push(pluginName)
50+
}
51+
52+
await updateConfig('runelite.externalPlugins', externalPlugins.join(','))
53+
await fetchConfig()
54+
}
55+
3656
const PluginHub = ({
3757
author,
3858
externalPlugins,
59+
configExternalPlugins,
3960
pluginFilter,
4061
pluginSorting,
4162
setPluginFilter,
42-
setPluginSorting
63+
setPluginSorting,
64+
updateConfig,
65+
fetchConfig,
66+
modifiedKeys,
67+
loggedIn
4368
}) => {
44-
externalPlugins = externalPlugins.filter(plugin =>
69+
externalPlugins = [...externalPlugins].filter(plugin =>
4570
author ? plugin.author === author : true
4671
)
4772

4873
const pluginCount = externalPlugins.length
4974
const installedPluginCount = externalPlugins.filter(p => p.installed).length
5075
const totalCount = externalPlugins.reduce((a, b) => a + b.count, 0)
76+
const updateFunction = handleUpdate(
77+
updateConfig,
78+
fetchConfig,
79+
configExternalPlugins
80+
)
5181
const sortChoices = ['active installs', 'name', 'time updated', 'time added']
5282

5383
if (installedPluginCount > 0) {
@@ -115,9 +145,28 @@ const PluginHub = ({
115145
/>
116146
</div>
117147
</div>
148+
{modifiedKeys.includes('runelite.externalPlugins') && (
149+
<div
150+
style={{
151+
background: '#1e1e1e'
152+
}}
153+
class="p-3"
154+
>
155+
<span class="badge badge-warning">
156+
<b>Warning</b>
157+
</span>{' '}
158+
Installing and uninstalling plugins through this interface
159+
requires client restart.
160+
</div>
161+
)}
118162
<div class="row">
119163
{externalPlugins.map(plugin => (
120-
<ExternalPlugin key={plugin.internalName} {...plugin} />
164+
<ExternalPlugin
165+
key={plugin.internalName}
166+
{...plugin}
167+
update={updateFunction}
168+
showInstall={loggedIn}
169+
/>
121170
))}
122171
</div>
123172
</div>
@@ -129,8 +178,11 @@ const PluginHub = ({
129178
const mapStateToProps = (state, props) => ({
130179
...props,
131180
externalPlugins: getSortedExternalPlugins(state),
181+
configExternalPlugins: getExternalPlugins(state),
132182
pluginFilter: getPluginFilter(state),
133-
pluginSorting: getPluginSorting(state)
183+
pluginSorting: getPluginSorting(state),
184+
modifiedKeys: getModifiedKeys(state),
185+
loggedIn: isLoggedIn(state)
134186
})
135187

136188
const mapDispatchToProps = dispatch =>
@@ -141,7 +193,8 @@ const mapDispatchToProps = dispatch =>
141193
fetchExternalPlugins,
142194
fetchPluginHubStats,
143195
setPluginFilter,
144-
setPluginSorting
196+
setPluginSorting,
197+
updateConfig
145198
},
146199
dispatch
147200
)

src/store.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ export default callback => {
1616

1717
// Add logger
1818
if (isDebug) {
19-
middlewares.push(require('redux-logger').default)
19+
const { createLogger } = require('redux-logger')
20+
middlewares.push(
21+
createLogger({
22+
diff: true
23+
})
24+
)
2025
}
2126

2227
// Create reducer

0 commit comments

Comments
 (0)