Jeremy D commited on 2021-09-04 07:46:08
Showing 7 changed files, with 410 additions and 0 deletions.
... | ... |
@@ -0,0 +1,29 @@ |
1 |
+BSD 3-Clause License |
|
2 |
+ |
|
3 |
+Copyright (c) 2021, SleePy |
|
4 |
+All rights reserved. |
|
5 |
+ |
|
6 |
+Redistribution and use in source and binary forms, with or without |
|
7 |
+modification, are permitted provided that the following conditions are met: |
|
8 |
+ |
|
9 |
+1. Redistributions of source code must retain the above copyright notice, this |
|
10 |
+ list of conditions and the following disclaimer. |
|
11 |
+ |
|
12 |
+2. Redistributions in binary form must reproduce the above copyright notice, |
|
13 |
+ this list of conditions and the following disclaimer in the documentation |
|
14 |
+ and/or other materials provided with the distribution. |
|
15 |
+ |
|
16 |
+3. Neither the name of the copyright holder nor the names of its |
|
17 |
+ contributors may be used to endorse or promote products derived from |
|
18 |
+ this software without specific prior written permission. |
|
19 |
+ |
|
20 |
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
21 |
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
22 |
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
23 |
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
|
24 |
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
25 |
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|
26 |
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|
27 |
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
|
28 |
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
29 |
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
... | ... |
@@ -0,0 +1,7 @@ |
1 |
+A customization for SMF 2.0 or 2.1. |
|
2 |
+ |
|
3 |
+This enables SMF to do Web App. This is called Web Clip by Apple and WebView by Android. Also known may be knkown as a Progressive Web App |
|
4 |
+ |
|
5 |
+This just adds the headers and manifest to allow devices to treat it as a app. |
|
6 |
+ |
|
7 |
+This was quickly writen with minimal testing and support. |
|
0 | 8 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,270 @@ |
1 |
+<?php |
|
2 |
+ |
|
3 |
+/** |
|
4 |
+ * The Main class for Web App |
|
5 |
+ * @package WebApp |
|
6 |
+ * @author SleePy <sleepy @ simplemachines (dot) org> |
|
7 |
+ * @copyright 2021 |
|
8 |
+ * @license 3-Clause BSD https://opensource.org/licenses/BSD-3-Clause |
|
9 |
+ * @version 1.0 |
|
10 |
+ */ |
|
11 |
+class WebApp |
|
12 |
+{ |
|
13 |
+ public static $DisplayOptions = [ |
|
14 |
+ 0 => 'standalone', |
|
15 |
+ 1 => 'fullscreen', |
|
16 |
+ 2 => 'minimal', |
|
17 |
+ 3 => 'browser', |
|
18 |
+ ]; |
|
19 |
+ |
|
20 |
+ public static $OrientationOptions = [ |
|
21 |
+ 0 => 'any', |
|
22 |
+ 1 => 'natural', |
|
23 |
+ 2 => 'landscape-primary', |
|
24 |
+ 3 => 'landscape-secondary', |
|
25 |
+ 4 => 'portrait', |
|
26 |
+ 5 => 'portrait-primary', |
|
27 |
+ 6 => 'portrait-secondary', |
|
28 |
+ ]; |
|
29 |
+ |
|
30 |
+ // The default manifest |
|
31 |
+ public static $default_manifest = [ |
|
32 |
+ 'name' => null, |
|
33 |
+ 'short_name' => null, |
|
34 |
+ 'theme_color' => '#03173d', |
|
35 |
+ 'background_color' => 'standalone', |
|
36 |
+ 'orientation' => 'portrait', |
|
37 |
+ 'scope' => null, |
|
38 |
+ 'start_url' => null, |
|
39 |
+ 'icons' => [ |
|
40 |
+ 'src' => 'favicon.ico', |
|
41 |
+ 'type' => 'image/x-icon', |
|
42 |
+ 'sizes' => '512x512' |
|
43 |
+ ] |
|
44 |
+ ]; |
|
45 |
+ |
|
46 |
+ // Orientation, display and icons are handled separtely. |
|
47 |
+ public static $all_options = [ |
|
48 |
+ 'name', 'short_name', 'theme_color', 'background_color', 'scope', 'start_url' |
|
49 |
+ ]; |
|
50 |
+ |
|
51 |
+ /** |
|
52 |
+ * Adds in the headers we need for the webapp. |
|
53 |
+ * |
|
54 |
+ * @api |
|
55 |
+ * @CalledIn SMF 2.1 |
|
56 |
+ * @version 1.0 |
|
57 |
+ * @since 1.0 |
|
58 |
+ * @uses integrate_load_theme - Hook SMF2.1 |
|
59 |
+ * @return void No return is generated |
|
60 |
+ */ |
|
61 |
+ public static function hook_load_theme(): void |
|
62 |
+ { |
|
63 |
+ global $context, $boardurl, $scripturl; |
|
64 |
+ |
|
65 |
+ // Add the meta tags in. |
|
66 |
+ $context['meta_tags'][] = ['name' => 'apple-mobile-web-app-capable', 'content' => 'yes']; |
|
67 |
+ $context['meta_tags'][] = ['name' => 'mobile-wep-app-capable', 'content' => 'yes']; |
|
68 |
+ $context['meta_tags'][] = ['name' => 'apple-mobile-web-app-status-bar-style', 'content' => 'black']; |
|
69 |
+ |
|
70 |
+ $icon = $boardurl . '/favicon.ico'; |
|
71 |
+ |
|
72 |
+ // No good place to call these in the header, so just put them into html_headers. |
|
73 |
+ $context['html_headers'] .= ' |
|
74 |
+ <link rel="apple-touch-icon" sizes="192x192" href="' . $icon . '"> |
|
75 |
+ <link rel="manifest" href="' . $scripturl . '?action=manifest;v=1">'; |
|
76 |
+ } |
|
77 |
+ |
|
78 |
+ /** |
|
79 |
+ * Adds in a action for us to call later. |
|
80 |
+ * |
|
81 |
+ * @api |
|
82 |
+ * @CalledIn SMF 2.1 |
|
83 |
+ * @version 1.0 |
|
84 |
+ * @since 1.0 |
|
85 |
+ * @uses integrate_actions - Hook SMF2.1 |
|
86 |
+ * @return void |
|
87 |
+ */ |
|
88 |
+ public static function hook_actions(array &$actionArray): void |
|
89 |
+ { |
|
90 |
+ $actionArray['manifest'] = ['WebApp.php', 'WebApp::hook_action_called']; |
|
91 |
+ } |
|
92 |
+ |
|
93 |
+ /** |
|
94 |
+ * Called by SMF if we call the action=maniffest. |
|
95 |
+ * |
|
96 |
+ * @api |
|
97 |
+ * @CalledIn SMF 2.1 |
|
98 |
+ * @version 1.0 |
|
99 |
+ * @since 1.0 |
|
100 |
+ * @uses integrate_actions - Hook SMF2.1 |
|
101 |
+ * @return void |
|
102 |
+ */ |
|
103 |
+ public static function hook_action_called(): void |
|
104 |
+ { |
|
105 |
+ global $mbname, $boardurl, $scripturl, $modSettings, $txt, $context; |
|
106 |
+ |
|
107 |
+ $manifest = array_merge(self::$default_manifest, [ |
|
108 |
+ 'name' => $mbname, |
|
109 |
+ 'short_name' => substr($mbname, 0, 15), |
|
110 |
+ 'scope' => $boardurl, |
|
111 |
+ 'start_url' => $scripturl, |
|
112 |
+ 'icons' => [ |
|
113 |
+ 'src' => $boardurl . '/favicon.ico', |
|
114 |
+ ] |
|
115 |
+ ]); |
|
116 |
+ |
|
117 |
+ // The settings we have. |
|
118 |
+ if (isset($modSettings['webapp_display'])) |
|
119 |
+ $manifest['display'] = self::$DisplayOptions[$modSettings['webapp_display']]; |
|
120 |
+ if (isset($modSettings['webapp_display'])) |
|
121 |
+ $manifest['orientation'] = self::$OrientationOptions[$modSettings['webapp_orientation']]; |
|
122 |
+ |
|
123 |
+ // Set some standard settings the easy way. |
|
124 |
+ foreach (self::$all_options as $opt) |
|
125 |
+ if (isset($modSettings['webapp_' . $opt]) && $modSettings['webapp_' . $opt] != '') |
|
126 |
+ $manifest[$opt] = (string) $modSettings['webapp_' . $opt]; |
|
127 |
+ |
|
128 |
+ // May be a better way to do this. This also may not be the best way to do this. |
|
129 |
+ $manifest['lang'] = $txt['lang_locale']; |
|
130 |
+ if (!empty($context['right_to_left'])) |
|
131 |
+ $manifest['dir'] = 'rtl'; |
|
132 |
+ |
|
133 |
+ // Do we have a icon? The specification allows multiple icons. Do we really want to implant that? |
|
134 |
+ // We don't implant sizes (space separated list) or purpose. |
|
135 |
+ if (!empty($modSettings['webapp_icon'])) |
|
136 |
+ { |
|
137 |
+ $manifest['icons']['src'] = $modSettings['webapp_icon']; |
|
138 |
+ $manifest['icons']['type'] = $modSettings['webapp_icon_type']; |
|
139 |
+ } |
|
140 |
+ |
|
141 |
+ /* Not implanted specification items |
|
142 |
+ categories - SMF doesn't have a place to track a forum's purpose that fits in the usual cateogires: https://github.com/w3c/manifest/wiki/Categories |
|
143 |
+ description - We could use the slogan from the theme, but this doesn't provide much benefit really. |
|
144 |
+ iarc_rating_id - There is a process to get a rating, so most forums won't do this. |
|
145 |
+ related_applications - Doesn't seem relevant to link to other applications. |
|
146 |
+ prefer_related_applications - Doesn't seem relevant to link to other applications. |
|
147 |
+ shortcuts - Contextual menu driven here seems like things could get difficult and messy. |
|
148 |
+ screenshots - Seems only necessary if your submitting it to a store. |
|
149 |
+ */ |
|
150 |
+ |
|
151 |
+ ob_end_clean(); |
|
152 |
+ header('Content-Type: application/json; charset=UTF8'); |
|
153 |
+ echo json_encode($manifest); |
|
154 |
+ die; |
|
155 |
+ } |
|
156 |
+ |
|
157 |
+ /** |
|
158 |
+ * Startup the Admin Panels Additions. |
|
159 |
+ * |
|
160 |
+ * @param array $admin_areas A associate array from the software with all valid admin areas. |
|
161 |
+ * |
|
162 |
+ * @api |
|
163 |
+ * @CalledIn SMF 2.1 |
|
164 |
+ * @version 1.0 |
|
165 |
+ * @since 1.0 |
|
166 |
+ * @uses integrate_admin_areas - Hook SMF2.1 |
|
167 |
+ * @return void |
|
168 |
+ */ |
|
169 |
+ public static function hook_admin_areas(array &$admin_areas): void |
|
170 |
+ { |
|
171 |
+ global $txt; |
|
172 |
+ |
|
173 |
+ loadLanguage('WebApp'); |
|
174 |
+ $admin_areas['config']['areas']['modsettings']['subsections']['webapp'] = [$txt['webapp_title']]; |
|
175 |
+ } |
|
176 |
+ |
|
177 |
+ /** |
|
178 |
+ * For the help function, load up our text. |
|
179 |
+ * |
|
180 |
+ * |
|
181 |
+ * @api |
|
182 |
+ * @CalledIn SMF 2.1 |
|
183 |
+ * @version 1.0 |
|
184 |
+ * @since 1.0 |
|
185 |
+ * @uses integrate_helpadmin - Hook SMF2.1 |
|
186 |
+ * @return void |
|
187 |
+ */ |
|
188 |
+ public static function hook_helpadmin(): void |
|
189 |
+ { |
|
190 |
+ loadLanguage('WebApp'); |
|
191 |
+ } |
|
192 |
+ |
|
193 |
+ /** |
|
194 |
+ * Setup the Modification's setup page. |
|
195 |
+ * For some versions, we put the logs into the modifications sections, its easier. |
|
196 |
+ * |
|
197 |
+ * @param array $subActions A associate array from the software with all valid modification sections. |
|
198 |
+ * |
|
199 |
+ * @api |
|
200 |
+ * @CalledIn SMF 2.1 |
|
201 |
+ * @see SFSA::setupModifyModifications() |
|
202 |
+ * @version 1.0 |
|
203 |
+ * @since 1.0 |
|
204 |
+ * @uses integrate_modify_modifications - Hook SMF2.0 |
|
205 |
+ * @uses integrate_modify_modifications - Hook SMF2.1 |
|
206 |
+ * @return void |
|
207 |
+ */ |
|
208 |
+ public static function hook_modify_modifications(array &$subActions): void |
|
209 |
+ { |
|
210 |
+ $subActions['webapp'] = 'WebApp::startupAdminConfiguration'; |
|
211 |
+ } |
|
212 |
+ |
|
213 |
+ /** |
|
214 |
+ * The actual settings page. |
|
215 |
+ * |
|
216 |
+ * @param bool $return_config If true, returns the configuration options for searches. |
|
217 |
+ * |
|
218 |
+ * @internal |
|
219 |
+ * @CalledIn SMF 2.0, SMF 2.1 |
|
220 |
+ * @version 1.0 |
|
221 |
+ * @since 1.0 |
|
222 |
+ * @uses integrate_modify_modifications - Hook SMF2.0 |
|
223 |
+ * @uses integrate_modify_modifications - Hook SMF2.1 |
|
224 |
+ * @return array But only when searching |
|
225 |
+ */ |
|
226 |
+ public static function startupAdminConfiguration(bool $return_config = false): array |
|
227 |
+ { |
|
228 |
+ global $txt, $scripturl, $context, $settings, $sc, $modSettings; |
|
229 |
+ |
|
230 |
+ $displayOptions = []; |
|
231 |
+ foreach (self::$DisplayOptions as $idx => $val) |
|
232 |
+ $displayOptions[$idx] = $txt['webapp_display_' . $val]; |
|
233 |
+ |
|
234 |
+ $orientationOptions = []; |
|
235 |
+ foreach (self::$OrientationOptions as $idx => $val) |
|
236 |
+ $orientationOptions[$idx] = $txt['webapp_orientation_' . $val]; |
|
237 |
+ |
|
238 |
+ $config_vars = [ |
|
239 |
+ ['title', 'webappgentitle', 'label' => $txt['webapp_title']], |
|
240 |
+ |
|
241 |
+ ['check', 'webapp_enabled'], |
|
242 |
+ ['text', 'webapp_theme_color'], |
|
243 |
+ ['text', 'webapp_background_color'], |
|
244 |
+ '', |
|
245 |
+ ['text', 'webapp_icon'], |
|
246 |
+ ['select', 'webapp_icon_type', ['image/png', 'image/jpg', 'image/svg', 'image/webp']], |
|
247 |
+ ['select', 'webapp_display', $displayOptions], |
|
248 |
+ ['select', 'webapp_orientation', $orientationOptions], |
|
249 |
+ ]; |
|
250 |
+ |
|
251 |
+ if ($return_config) |
|
252 |
+ return $config_vars; |
|
253 |
+ |
|
254 |
+ // Saving? |
|
255 |
+ if (isset($_GET['save'])) |
|
256 |
+ { |
|
257 |
+ checkSession(); |
|
258 |
+ |
|
259 |
+ saveDBSettings($config_vars); |
|
260 |
+ |
|
261 |
+ writeLog(); |
|
262 |
+ redirectexit($scripturl . '?action=admin;area=modsettings;sa=webapp'); |
|
263 |
+ } |
|
264 |
+ |
|
265 |
+ $context['post_url'] = $scripturl . '?action=admin;area=modsettings;sa=webapp' . ';save'; |
|
266 |
+ prepareDBSettingContext($config_vars); |
|
267 |
+ |
|
268 |
+ return []; |
|
269 |
+ } |
|
270 |
+} |
|
0 | 271 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,47 @@ |
1 |
+<?php |
|
2 |
+ |
|
3 |
+global $helptxt; |
|
4 |
+ |
|
5 |
+/* The section Name */ |
|
6 |
+$txt['webapp_title'] = 'Web App'; |
|
7 |
+ |
|
8 |
+/* Admin section configuration options */ |
|
9 |
+$txt['webapp_enabled'] = 'Enable WebClip?'; |
|
10 |
+ |
|
11 |
+/* The Short name */ |
|
12 |
+$txt['webapp_shortname'] = 'Short Name'; |
|
13 |
+$txt['webapp_shortname'] = 'Short name is used on devices that do not have enough room to display the full name. Keep this short as some devices this is limited to 12 or less characters. |
|
14 |
+ |
|
15 |
+See <a href="https://developer.mozilla.org/en-US/docs/Web/Manifest/short_name">Web Manifest</a> for more information'; |
|
16 |
+ |
|
17 |
+/* An icon */ |
|
18 |
+$txt['webapp_icon'] = 'Webclip Icon'; |
|
19 |
+ |
|
20 |
+ |
|
21 |
+/* Background color */ |
|
22 |
+$txt['webapp_background_color'] = 'Background Color'; |
|
23 |
+$helptxt['webapp_background_color'] = 'The background_color defines a splash screen color to show while loading before the style sheet has finished. Use <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color_value">CSS Legal Color Values</a> |
|
24 |
+See <a href="https://developer.mozilla.org/en-US/docs/Web/Manifest/background_color">Web Manifest</a> for more information'; |
|
25 |
+ |
|
26 |
+/* Theme color */ |
|
27 |
+$txt['webapp_theme_color'] = 'Theme Color'; |
|
28 |
+$helptxt['webapp_theme_color'] = 'The theme_color how the OS colors around the app. Use <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color_value">CSS Legal Color Values</a> |
|
29 |
+See <a href="https://developer.mozilla.org/en-US/docs/Web/Manifest/theme_color">Web Manifest</a> for more information'; |
|
30 |
+ |
|
31 |
+/* Admin Section: Web app Display mode */ |
|
32 |
+$txt['webapp_display'] = 'Display'; |
|
33 |
+$txt['webapp_display_standalone'] = 'Standalone'; |
|
34 |
+$txt['webapp_display_fullscreen'] = 'Fullscreen'; |
|
35 |
+$txt['webapp_display_minimal'] = 'Minimal-ui'; |
|
36 |
+$txt['webapp_display_browser'] = 'Browser'; |
|
37 |
+ |
|
38 |
+/* Admin Section: Web app Display mode */ |
|
39 |
+$txt['webapp_orientation'] = 'Orientation'; |
|
40 |
+$txt['webapp_orientation_any'] = 'Any'; |
|
41 |
+$txt['webapp_orientation_natural'] = 'Natural'; |
|
42 |
+$txt['webapp_orientation_landscape'] = 'Landscape'; |
|
43 |
+$txt['webapp_orientation_landscape-primary'] = 'Landscape-primary'; |
|
44 |
+$txt['webapp_orientation_landscape-secondary'] = 'Landscape-secondary'; |
|
45 |
+$txt['webapp_orientation_portrait'] = 'Portrait'; |
|
46 |
+$txt['webapp_orientation_portrait-primary'] = 'Portrait-primary'; |
|
47 |
+$txt['webapp_orientation_portrait-secondary'] = 'Portrait-secondary'; |
|
0 | 48 |
\ No newline at end of file |
... | ... |
@@ -0,0 +1,46 @@ |
1 |
+<?xml version="1.0"?> |
|
2 |
+<!DOCTYPE package-info SYSTEM "http://www.simplemachines.org/xml/package-info"> |
|
3 |
+<package-info xmlns="http://www.simplemachines.org/xml/package-info" xmlns:smf="http://www.simplemachines.org/"> |
|
4 |
+ <id>SleePy:WebApp</id> |
|
5 |
+ <name>Web App</name> |
|
6 |
+ <version>1.0</version> |
|
7 |
+ <type>modification</type> |
|
8 |
+ |
|
9 |
+ <install for="2.1 RC4, 2.1.*"> |
|
10 |
+ <require-file name="language/WebApp.english.php" destination="$themes_dir/default/languages" /> |
|
11 |
+ <require-file name="WebApp.php" destination="$sourcedir" /> |
|
12 |
+ |
|
13 |
+ <!-- All the hooks --> |
|
14 |
+ <!-- Main Section --> |
|
15 |
+ <hook hook="integrate_pre_include" function="$sourcedir/WebApp.php" /> |
|
16 |
+ <hook hook="integrate_actions" function="WebApp::hook_actions" /> |
|
17 |
+ <hook hook="integrate_load_theme" function="WebApp::hook_load_theme" /> |
|
18 |
+ |
|
19 |
+ <!-- Admin Section --> |
|
20 |
+ <hook hook="integrate_admin_areas" function="WebApp::hook_admin_areas" /> |
|
21 |
+ <hook hook="integrate_modify_modifications" function="WebApp::hook_modify_modifications" /> |
|
22 |
+ <hook hook="integrate_helpadmin" function="WebApp::hook_helpadmin" /> |
|
23 |
+ |
|
24 |
+ <redirect url="?action=admin;area=securitysettings;sa=sfs" /> |
|
25 |
+ </install> |
|
26 |
+ |
|
27 |
+ <uninstall for="2.1 RC4, 2.1.*"> |
|
28 |
+ <!-- All the hooks, removed --> |
|
29 |
+ <!-- Main Section --> |
|
30 |
+ <hook hook="integrate_pre_include" function="$sourcedir/SFS.php" reverse="true" /> |
|
31 |
+ <hook hook="integrate_actions" function="SFS::hook_actions" reverse="true" /> |
|
32 |
+ <hook hook="integrate_load_theme" function="WebApp::hook_load_theme" reverse="true" /> |
|
33 |
+ |
|
34 |
+ <!-- Admin Section --> |
|
35 |
+ <hook hook="integrate_admin_areas" function="SFSA::hook_admin_areas" reverse="true" /> |
|
36 |
+ <hook hook="integrate_modify_modifications" function="WebApp::hook_modify_modifications" reverse="true" /> |
|
37 |
+ <hook hook="integrate_helpadmin" function="WebApp::hook_helpadmin" reverse="true" /> |
|
38 |
+ |
|
39 |
+ <!-- language files, removed --> |
|
40 |
+ <remove-file name="$themes_dir/default/languages/WebApp.english.php" /> |
|
41 |
+ |
|
42 |
+ <!-- source files, removed --> |
|
43 |
+ <remove-file name="$sourcedir/WebApp.php" /> |
|
44 |
+ </uninstall> |
|
45 |
+ |
|
46 |
+</package-info> |
|
0 | 47 |
\ No newline at end of file |
1 | 48 |