A basic mod for SMF that enables web app/pwa/web clip/web view/whatever to SMF
Jeremy D

Jeremy D commited on 2021-09-04 07:46:08
Showing 7 changed files, with 410 additions and 0 deletions.

... ...
@@ -0,0 +1,11 @@
1
+# Force our line endings to be LF, even for Windows
2
+* text=auto
3
+
4
+# Set certain files to be binary
5
+*.png binary
6
+*.jpg binary
7
+*.gif binary
8
+*.tgz binary
9
+*.zip binary
10
+*.tar.gz binary
11
+*.ttf binary
... ...
@@ -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