mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-21 00:52:33 -04:00
version 10.4.1
This commit is contained in:
16
CHANGELOG
16
CHANGELOG
@@ -1,3 +1,19 @@
|
||||
Hubzilla 10.4.1 (2025-07-31)
|
||||
- Fix regression in pubstream tag view
|
||||
- Fix photos meta data not updated when renaming folder in files app
|
||||
- Fix syntax error in custom emoji sample code
|
||||
- Fix rendering issue when image load event triggered after timeout
|
||||
- Fix comment preview not always displayed
|
||||
- Fix new created comment rendering offscreen
|
||||
- Update derived theme tutorial and add it to the help index
|
||||
- Add 'extends' attribute to theme info
|
||||
- Fix reply modal remaining hidden after reactions loaded
|
||||
- Refactor tagcloud to use smarty template file
|
||||
- Fix regression in tagadelic
|
||||
- Fix possible performance issue with archive widget
|
||||
- Fix various addons which still used the deprecated $a global
|
||||
|
||||
|
||||
Hubzilla 10.4 (2025-07-15)
|
||||
- Add support for did:key verification method to checkEddsaSignature()
|
||||
- Introduce util/init_sys_channel to create the sys channel if required
|
||||
|
||||
@@ -137,7 +137,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
|
||||
'$search' => '',
|
||||
'$xchan' => '',
|
||||
'$order' => 'comment',
|
||||
'$order' => 'post',
|
||||
'$file' => '',
|
||||
'$cats' => '',
|
||||
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
|
||||
@@ -173,17 +173,15 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
$site_firehose_sql = " and owner_xchan in (select channel_hash from channel where channel_system = 0 and channel_removed = 0) ";
|
||||
}
|
||||
|
||||
if(Config::Get('system','public_list_mode'))
|
||||
$page_mode = 'list';
|
||||
else
|
||||
$page_mode = 'client';
|
||||
$page_mode = 'client';
|
||||
$blog_mode = Config::Get('system',' public_list_mode');
|
||||
|
||||
if ($blog_mode) {
|
||||
$page_mode = 'list';
|
||||
}
|
||||
|
||||
if(x($hashtags)) {
|
||||
$sql_extra .= protect_sprintf(term_query('item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
|
||||
$sql_extra_order = " ORDER BY item.created DESC ";
|
||||
$thread_top = '';
|
||||
|
||||
}
|
||||
|
||||
$net_query2 = (($net) ? " and xchan_network = '" . protect_sprintf(dbesc($net)) . "' " : '');
|
||||
@@ -247,30 +245,20 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
// Then fetch all the children of the parents that are on this page
|
||||
$parents_str = '';
|
||||
|
||||
if($r) {
|
||||
$items = items_by_parent_ids($r);
|
||||
$items = items_by_parent_ids($r, blog_mode: $blog_mode);
|
||||
|
||||
// use effective_uid param of xchan_query to help sort out comment permission
|
||||
// for sys_channel owned items.
|
||||
|
||||
xchan_query($items, true, local_channel());
|
||||
$items = fetch_post_tags($items,true);
|
||||
|
||||
if (!$hashtags) {
|
||||
$items = conv_sort($items, $ordering);
|
||||
}
|
||||
|
||||
|
||||
$items = conv_sort($items, $ordering);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$mode = (($hashtags) ? 'pubstream-new' : 'pubstream');
|
||||
|
||||
$o .= conversation($items,$mode,$update,$page_mode);
|
||||
$o .= conversation($items, 'pubstream', $update, $page_mode);
|
||||
|
||||
if($mid)
|
||||
$o .= '<div id="content-complete"></div>';
|
||||
|
||||
2
boot.php
2
boot.php
@@ -70,7 +70,7 @@ require_once('include/security.php');
|
||||
|
||||
|
||||
define('PLATFORM_NAME', 'hubzilla');
|
||||
define('STD_VERSION', '10.4');
|
||||
define('STD_VERSION', '10.4.1');
|
||||
define('ZOT_REVISION', '6.0');
|
||||
|
||||
define('DB_UPDATE_VERSION', 1263);
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
<div id="developers" class="doco-section">
|
||||
<div class="vstack">
|
||||
<a class="" href="/help/developer/developers_guide">Guide</a>
|
||||
<a href="/help/tutorials/derived_theme">Tutorial: Creating a derived theme</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
### Creating a Derived Theme
|
||||
|
||||
**Lesson 1**
|
||||
|
||||
A derived theme takes most of the settings from its "parent" theme and lets you change a few things to your liking without creating an entire theme package.
|
||||
|
||||
|
||||
To create a derived theme, first choose a name. For our example we'll call our theme 'mytheme'. Hopefully you'll be a bit more creative. But throughout this document, wherever you see 'mytheme', replace that with the name you chose.
|
||||
|
||||
**Directory Structure**
|
||||
|
||||
First you need to create a theme directory structure. We'll keep it simple. We need a php directory and a css directory. Here are the Unix/Linux commands to do this. Assume that 'mywebsite' is your top level hubzilla folder.
|
||||
|
||||
|
||||
cd mywebsite
|
||||
mkdir view/theme/mytheme
|
||||
mkdir view/theme/mytheme/css
|
||||
mkdir view/theme/mytheme/php
|
||||
|
||||
|
||||
Great. Now we need a couple of files. The first one is your theme info file, which describes the theme.
|
||||
|
||||
It will be called view/theme/mytheme/php/theme.php (clever name huh?)
|
||||
|
||||
Inside it, put the following information - edit as needed
|
||||
|
||||
<?php
|
||||
|
||||
/**
|
||||
* * Name: Mytheme
|
||||
* * Description: Sample Derived theme
|
||||
* * Version: 1.0
|
||||
* * Author: Your Name
|
||||
* * Compat: Red [*]
|
||||
*
|
||||
*/
|
||||
|
||||
function mytheme_init(&$a) {
|
||||
|
||||
App::$theme_info['extends'] = 'redbasic';
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
Remember to rename the mytheme_init function with your theme name. In this case we will be extending the theme 'redbasic'.
|
||||
|
||||
|
||||
Now create another file. We call this a PCSS file, but it's really a PHP file.
|
||||
|
||||
The file is called view/theme/mytheme/php/style.php
|
||||
|
||||
In it, put the following:
|
||||
|
||||
<?php
|
||||
|
||||
require_once('view/theme/redbasic/php/style.php');
|
||||
|
||||
echo @file_get_contents('view/theme/mytheme/css/style.css');
|
||||
|
||||
|
||||
|
||||
That's it. This tells the software to read the PCSS information for the redbasic theme first, and then read our CSS file which will just consist of changes we want to make from our parent theme (redbasic).
|
||||
|
||||
Now create the actual CSS file for your theme. Put it in view/theme/mytheme/css/style.css (where we just told the software to look for it). For our example, we'll just change the body background color so you can see that it works. You can use any CSS you'd like.
|
||||
|
||||
|
||||
body {
|
||||
background-color: #DDD;
|
||||
}
|
||||
|
||||
|
||||
You've just successfully created a derived theme. This needs to be enabled in the admin "themes" panel, and then anybody on the site can use it by selecting it in Settings->Display Settings as their default theme.
|
||||
|
||||
**Lesson 2**
|
||||
|
||||
If you want to use the redbasic schemas for your derived theme, you have to do a bit more.
|
||||
|
||||
Do everything as above, but don't create view/theme/mytheme/php/style.php, but copy instead view/theme/redbasic/php/style.php to view/theme/mytheme/php/style.php. Modify that file and remove (or comment out) these two lines:
|
||||
|
||||
if(local_channel() && App::$channel && App::$channel['channel_theme'] != 'redbasic')
|
||||
set_pconfig(local_channel(), 'redbasic', 'schema', '---');
|
||||
|
||||
Also add this line at the bottom:
|
||||
|
||||
echo @file_get_contents('view/theme/mytheme/css/style.css');
|
||||
|
||||
To show the schema selector you have to copy view/theme/redbasic/tpl/theme_settings.tpl to view/theme/mytheme/tpl/theme_settings.tpl. Modify that file and replace the lines:
|
||||
|
||||
{{if $theme == redbasic}}
|
||||
{{include file="field_select.tpl" field=$schema}}
|
||||
{{/if}}
|
||||
|
||||
with:
|
||||
|
||||
{{include file="field_select.tpl" field=$schema}}
|
||||
140
doc/en/tutorials/derived_theme.md
Normal file
140
doc/en/tutorials/derived_theme.md
Normal file
@@ -0,0 +1,140 @@
|
||||
## Creating a Derived Theme
|
||||
|
||||
In this tutorial, we will learn how to make a derived theme. This is a theme that takes most of the settings from its "parent" theme and lets you change a few things to your liking without creating an entire theme package. This is a good starting point if you just want to change a few things from an existing theme, for example to give your hub a bit of personalised appearance.
|
||||
|
||||
We will use the standard 'redbasic' theme for our parent theme in this tutorial. You may have to make some adaptions if you want to use another theme as your base, but the process will be the same.
|
||||
|
||||
### Lesson 1 – Getting started
|
||||
|
||||
To create a derived theme, first choose a name. For our example we'll call our theme 'mytheme'. Hopefully you'll be a bit more creative. But throughout this document, wherever you see 'mytheme', replace that with the name you chose.
|
||||
|
||||
#### Directory Structure
|
||||
|
||||
First you need to create a theme directory structure. We'll keep it simple. We need a php directory and a css directory. Here are the Unix/Linux commands to do this. Assume that 'mywebsite' is your top level $projectname folder.
|
||||
|
||||
```
|
||||
$ cd mywebsite
|
||||
$ mkdir view/theme/mytheme
|
||||
$ mkdir view/theme/mytheme/css
|
||||
$ mkdir view/theme/mytheme/php
|
||||
```
|
||||
|
||||
#### The Theme Info file
|
||||
|
||||
Great. Now we need a couple of files. The first one is your theme info file, which describes the theme.
|
||||
|
||||
It will be called `view/theme/mytheme/php/theme.php` (clever name huh?)
|
||||
|
||||
Inside it, put the following information - edit as needed
|
||||
|
||||
```php
|
||||
<?php
|
||||
/*
|
||||
* Name: Mytheme
|
||||
* Description: Sample Derived theme
|
||||
* Version: 1.0
|
||||
* Author: Your Name <your fedi handle (optional)>
|
||||
* Extends: redbasic
|
||||
*/
|
||||
```
|
||||
|
||||
The top comment in the file makes up the information that is used by $Projectname for the information about the theme. Each of the lines is a kayword followed by a colon and a value. Notice the last line in the comment: `Extends: redbasic`. This is what tells $Projectname that this is a derived theme, and that it should get any elements missing from this theme from the parent theme. In this case we will be extending the theme 'redbasic'.
|
||||
|
||||
We don't need any further code in this file for now, so just leave it empty.
|
||||
|
||||
#### The PCSS file and style.css
|
||||
|
||||
Now create another file. We call this a PCSS file, but it's really a PHP file.
|
||||
|
||||
The file is called `view/theme/mytheme/php/style.php`.
|
||||
|
||||
In it, put the following:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
define('MY_THEME_ROOT', dirname(__DIR__));
|
||||
define('PROJECT_THEME_ROOT', PROJECT_BASE . '/view/theme');
|
||||
|
||||
require_once(PROJECT_THEME_ROOT . '/redbasic/php/style.php');
|
||||
echo file_get_contents(MY_THEME_ROOT . '/css/style.css');
|
||||
```
|
||||
|
||||
That's it. This tells the software to read the PCSS information for the redbasic theme first, and then read our CSS file which will just consist of changes we want to make from our parent theme (redbasic).
|
||||
|
||||
Now create the actual CSS file for your theme. Put it in `view/theme/mytheme/css/style.css` (where we just told the software to look for it). For our example, we'll just change the body background colour so you can see that it works. You can use any CSS you'd like.
|
||||
|
||||
```css
|
||||
body {
|
||||
background-color: #DDD;
|
||||
}
|
||||
```
|
||||
|
||||
You've just successfully created a derived theme. This needs to be enabled in the admin "themes" panel, and then anybody on the site can use it by selecting it in Settings->Display Settings as their default theme.
|
||||
|
||||
#### Theme configuration and schemas
|
||||
|
||||
If you want to keep the various configuration options for the derived theme, you have to add a configuration class for your child theme.
|
||||
|
||||
Add another file, this time in `view/theme/mytheme/php/config.php`. Add the following content to it:
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace Zotlabs\Theme;
|
||||
|
||||
require_once 'view/theme/redbasic/php/config.php';
|
||||
|
||||
class MythemeConfig extends RedbasicConfig {
|
||||
}
|
||||
```
|
||||
|
||||
We leave the class itself empty, so that it will simply inherit the configuration and settings from the parent theme, in this case Redbasic. This will automatically make the settings and scheme selection from Redbasic available to your child theme as well.
|
||||
|
||||
### Lesson 2 - Customizing the theme
|
||||
|
||||
#### Adding custom styles
|
||||
|
||||
In the previous lesson we added a simple style in the `view/theme/mytheme/css/style.css` file, just so that we could see the that our derived theme was active.
|
||||
|
||||
We can of course add any styles we want to that file, and since we load it _after_ the parent theme's styles, we are able to override the styles provided by the parent theme, or by the $Projectname core. There's a lot that can be done with styling alone, and for many this will be all that you need to customize the theme to your liking.
|
||||
|
||||
#### Overriding templates
|
||||
|
||||
In some cases, overriding CSS styles may not be enough to get exactly the result you want from your theme. In these cases we can also override the templates used to build the HTML of the web pages itself.
|
||||
|
||||
Templates are the building blocks of the $Projectname web UI. They can be complex and contain the entire UI for a module, or simple building blocks like an input field or a button.
|
||||
|
||||
In this example we will modify the templates for checkboxes, changing them from the default toggle buttons used by Redbasic to a standard HTML checkbox.
|
||||
|
||||
This is what it looked like before the change:
|
||||
|
||||

|
||||
|
||||
The original template is located in `view/tpl/field_checkbox.tpl`. So the first thing we do is to copy this file into our theme's template directory, that is `view/theme/mytheme/tpl/field_checkbox.tpl`. Then change it as you want. For this example, we change it to the following:
|
||||
|
||||
```html
|
||||
<div id="{{$field.0}}_container" class="clearfix checkbox mb-3">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="{{$field.0}}"
|
||||
id="id_{{$field.0}}"
|
||||
value="1"
|
||||
{{if $field.2}}checked="checked"{{/if}}
|
||||
{{if $field.5}}{{$field.5}}{{/if}}
|
||||
>
|
||||
<label for="id_{{$field.0}}">
|
||||
{{$field.1}}{{if $field.6}}<sup class="required zuiqmid"> {{$field.6}}</sup>{{/if}}
|
||||
</label>
|
||||
<div class="form-text text-muted">{{$field.3}}</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
When looking for templates, $Projectname will first look for one in the theme's template directory, then (if relevant) in the parent theme's directory, and finally it will look in the `view/tpl` directory for the system defines templates. It will use the first template found.
|
||||
|
||||
This means that from now on, our theme's checkbox template will be used whenever the UI wants to display a checkbox.
|
||||
|
||||
This is how it looks with the change:
|
||||
|
||||

|
||||
|
||||
Also note that files should be places in subdirectories under our theme directory that matches the extension of the file. So `*.css` files should be in the `view/theme/mytheme/css` directory, `*.php` files in the `view/theme/mytheme/php` directory, and `*.tpl` files in the `view/theme/mytheme/tpl` directory.
|
||||
BIN
doc/en/tutorials/pic/override-template-after.png
Normal file
BIN
doc/en/tutorials/pic/override-template-after.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
BIN
doc/en/tutorials/pic/override-template-before.png
Normal file
BIN
doc/en/tutorials/pic/override-template-before.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -12,6 +12,6 @@ The content of custom_emojis.json should look as follows:
|
||||
"another_emoji": {
|
||||
"shortname": ":another_emoji:",
|
||||
"filepath": "images/emoji/custom/another_emoji.png"
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
@@ -2634,24 +2634,22 @@ function attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '',
|
||||
dbesc($resource_id)
|
||||
);
|
||||
|
||||
if ($recurse) {
|
||||
foreach($ps as $p) {
|
||||
q("update photo set album = '%s', filename = '%s', os_path = '%s', display_path = '%s', content = '%s'
|
||||
where resource_id = '%s' and imgscale = %d and uid = %d",
|
||||
dbesc($newalbumname),
|
||||
dbesc($filename),
|
||||
dbesc($x['os_path']),
|
||||
dbesc($x['path']),
|
||||
dbescbin($newstorepath . ((intval($p['imgscale']) > 0) ? '-' . $p['imgscale'] : '')),
|
||||
dbesc($resource_id),
|
||||
intval($p['imgscale']),
|
||||
intval($channel_id)
|
||||
);
|
||||
foreach($ps as $p) {
|
||||
q("update photo set album = '%s', filename = '%s', os_path = '%s', display_path = '%s', content = '%s'
|
||||
where resource_id = '%s' and imgscale = %d and uid = %d",
|
||||
dbesc($newalbumname),
|
||||
dbesc($filename),
|
||||
dbesc($x['os_path']),
|
||||
dbesc($x['path']),
|
||||
dbescbin($newstorepath . ((intval($p['imgscale']) > 0) ? '-' . $p['imgscale'] : '')),
|
||||
dbesc($resource_id),
|
||||
intval($p['imgscale']),
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
// the original should have been copied already
|
||||
if (intval($p['imgscale']) > 0) {
|
||||
rename($oldstorepath . '-' . $p['imgscale'], $newstorepath . '-' . $p['imgscale']);
|
||||
}
|
||||
// the original should have been copied already
|
||||
if ($recurse && intval($p['imgscale']) > 0) {
|
||||
rename($oldstorepath . '-' . $p['imgscale'], $newstorepath . '-' . $p['imgscale']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -769,7 +769,8 @@ function get_theme_info($theme){
|
||||
'experimental' => false,
|
||||
'unsupported' => false,
|
||||
'theme_color' => '',
|
||||
'background_color' => ''
|
||||
'background_color' => '',
|
||||
'extends' => '',
|
||||
);
|
||||
|
||||
if(file_exists("view/theme/$theme/experimental"))
|
||||
@@ -1077,10 +1078,11 @@ function theme_include($file, $root = '') {
|
||||
$root = $root . '/';
|
||||
$theme_info = App::$theme_info;
|
||||
|
||||
if(array_key_exists('extends',$theme_info))
|
||||
$parent = $theme_info['extends'];
|
||||
else
|
||||
if(empty($theme_info['extends'])) {
|
||||
$parent = 'NOPATH';
|
||||
} else {
|
||||
$parent = $theme_info['extends'];
|
||||
}
|
||||
|
||||
$theme = Zotlabs\Render\Theme::current();
|
||||
$thname = $theme[0];
|
||||
|
||||
@@ -323,12 +323,14 @@ function pubtagblock($net,$site,$limit,$recent = 0,$safemode = 1, $type = TERM_H
|
||||
|
||||
$link = z_root() . '/pubstream';
|
||||
|
||||
if($r) {
|
||||
$o = '<div class="tagblock widget"><h3>' . (($recent) ? t('Trending') : t('Tags')) . '</h3><div class="tags" align="center">';
|
||||
foreach($r as $rr) {
|
||||
$o .= '<span class="tag'.$rr[2].'">#</span><a href="'.$link . '?tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
|
||||
}
|
||||
$o .= '</div></div>';
|
||||
if ($r) {
|
||||
$url = $link . '?tag=';
|
||||
$tpl = get_markup_template('tagcloud.tpl');
|
||||
$o .= replace_macros($tpl, [
|
||||
'$title' => t('Trending'),
|
||||
'$baseurl' => $url,
|
||||
'$tags' => $r,
|
||||
]);
|
||||
}
|
||||
|
||||
return $o;
|
||||
@@ -369,9 +371,10 @@ function pub_tagadelic($net, $site, $limit, $recent, $safemode, $type) {
|
||||
$arr = [
|
||||
"SELECT term, count(term) AS total FROM term LEFT JOIN item ON term.oid = item.id
|
||||
WHERE term.ttype = %d
|
||||
AND otype = %d
|
||||
AND item_type = %d
|
||||
AND item_private = 0
|
||||
AND term.otype = %d
|
||||
AND item.item_type = %d
|
||||
AND item.item_private = 0
|
||||
AND item.id = item.parent
|
||||
$uids $item_normal $site_firehose_sql $sql_extra
|
||||
GROUP BY term ORDER BY total DESC %s",
|
||||
intval($type),
|
||||
@@ -484,11 +487,14 @@ function wtagblock($uid,$count = 0,$authors = '',$owner = '', $flags = 0,$restri
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
$o = '<div class="tagblock widget"><h3>' . t('Tags') . '</h3><div class="tags" align="center">';
|
||||
foreach($r as $rr) {
|
||||
$o .= '<span class="tag' . $rr[2] . '">#</span><a href="channel/' . $c[0]['channel_address'] . '?f=&tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
|
||||
}
|
||||
$o .= '</div></div>';
|
||||
$channel = App::get_channel();
|
||||
$url = z_root() . '/channel/' . $channel['channel_address'].'/?f=&tag=';
|
||||
$tpl = get_markup_template('tagcloud.tpl');
|
||||
$o .= replace_macros($tpl, [
|
||||
'$title' => t('Tags'),
|
||||
'$baseurl' => $url,
|
||||
'$tags' => $r,
|
||||
]);
|
||||
}
|
||||
|
||||
return $o;
|
||||
@@ -505,11 +511,13 @@ function catblock($uid,$count = 0,$authors = '',$owner = '', $flags = 0,$restric
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
$o = '<div class="tagblock widget"><h3>' . t('Categories') . '</h3><div class="tags" align="center">';
|
||||
foreach($r as $rr) {
|
||||
$o .= '<a href="channel/' . $c[0]['channel_address']. '?f=&cat=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
|
||||
}
|
||||
$o .= '</div></div>';
|
||||
$url = z_root() . '/channel/' . $c[0]['channel_address'].'/?f=&cat=';
|
||||
$tpl = get_markup_template('tagcloud.tpl');
|
||||
$o .= replace_macros($tpl, [
|
||||
'$title' => t('Categories'),
|
||||
'$baseurl' => $url,
|
||||
'$tags' => $r,
|
||||
]);
|
||||
}
|
||||
|
||||
return $o;
|
||||
@@ -564,13 +572,14 @@ function dir_tagblock($link,$r) {
|
||||
$r = App::$data['directory_keywords'] ?? [];
|
||||
|
||||
if($r) {
|
||||
$o = '<div class="dirtagblock widget"><h3>' . t('Keywords') . '</h3><div class="tags" align="center">';
|
||||
foreach($r as $rr) {
|
||||
$o .= '<a href="'.$link .'/' . '?f=&keywords=' . urlencode($rr['term']).'" class="tag'.$rr['normalise'].'" rel="nofollow" >'.$rr['term'].'</a> ' . "\r\n";
|
||||
}
|
||||
$o .= '</div></div>';
|
||||
$url = $link . '/?f=&keywords=';
|
||||
$tpl = get_markup_template('dirtagcloud.tpl');
|
||||
$o .= replace_macros($tpl, [
|
||||
'$title' => t('Keywords'),
|
||||
'$baseurl' => $url,
|
||||
'$tags' => $r,
|
||||
]);
|
||||
}
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
@@ -942,20 +942,20 @@ function updateConvItems(mode, data) {
|
||||
mediaPlaying = event.type === 'playing';
|
||||
}
|
||||
|
||||
imagesLoaded(document.querySelectorAll('.wall-item-body img, .wall-photo-item img'), function () {
|
||||
if (bParam_mid && mode === 'replace') {
|
||||
scrollToItem();
|
||||
}
|
||||
else {
|
||||
collapseHeight();
|
||||
}
|
||||
});
|
||||
if (bParam_mid && mode === 'replace') {
|
||||
scrollToItem();
|
||||
}
|
||||
|
||||
// reset rotators and cursors we may have set before reaching this place
|
||||
// A slight delay to give the browser time to render images.
|
||||
// Otherwise height calculation might not be accurate.
|
||||
setTimeout(collapseHeight, 10);
|
||||
|
||||
// Reset rotators and cursors we may have set before reaching this place
|
||||
let pageSpinner = document.getElementById("page-spinner");
|
||||
if (pageSpinner) {
|
||||
pageSpinner.style.display = 'none';
|
||||
}
|
||||
|
||||
let profileJotTextLoading = document.getElementById("profile-jot-text-loading");
|
||||
if (profileJotTextLoading) {
|
||||
profileJotTextLoading.style.display = 'none';
|
||||
@@ -971,6 +971,7 @@ function imagesLoaded(elements, callback) {
|
||||
let loadedCount = 0;
|
||||
let totalImages = 0;
|
||||
let timeoutId;
|
||||
let timedOut = false;
|
||||
const timeout = 10000;
|
||||
const processed = new Set(); // Use a Set for efficient lookup
|
||||
|
||||
@@ -982,6 +983,10 @@ function imagesLoaded(elements, callback) {
|
||||
}
|
||||
|
||||
function checkComplete(src) {
|
||||
// If preloading timed out make sure to not call the callback again
|
||||
// in case a load event listener fires later.
|
||||
if (timedOut) return;
|
||||
|
||||
// Skip processing if image has already been processed
|
||||
if (processed.has(src)) return;
|
||||
|
||||
@@ -1029,7 +1034,9 @@ function imagesLoaded(elements, callback) {
|
||||
// Set timeout for the loading process
|
||||
timeoutId = setTimeout(() => {
|
||||
console.warn(`Image loading timed out after ${timeout}ms`);
|
||||
document.getElementById('image_counter').innerText = '';
|
||||
callback(false);
|
||||
timedOut = true;
|
||||
}, timeout);
|
||||
|
||||
// Iterate through images to add load and error event listeners
|
||||
@@ -1771,6 +1778,7 @@ function doprofilelike(ident, verb) {
|
||||
|
||||
function doreply(parent, ident, owner, hint) {
|
||||
const modal = new bootstrap.Modal('#reactions');
|
||||
const modal_container = document.getElementById('reactions')
|
||||
const modal_content = document.getElementById('reactions_body');
|
||||
const modal_title = document.getElementById('reactions_title');
|
||||
const modal_action = document.getElementById('reactions_action');
|
||||
@@ -1779,23 +1787,28 @@ function doreply(parent, ident, owner, hint) {
|
||||
modal_title.innerHTML = hint;
|
||||
|
||||
const preview = document.getElementById('comment-edit-preview-' + parent.toString());
|
||||
preview.innerHTML = '';
|
||||
if (preview) preview.innerHTML = '';
|
||||
|
||||
const form_container = document.getElementById('comment-edit-wrapper-' + parent.toString());
|
||||
|
||||
// Get the form element by ID
|
||||
const form = document.getElementById('comment-edit-wrapper-' + parent.toString());
|
||||
const form = document.getElementById('comment-edit-form-' + parent.toString());
|
||||
if (!form) return;
|
||||
|
||||
modal_content.innerHTML = '';
|
||||
modal_content.append(form);
|
||||
modal_content.append(preview);
|
||||
|
||||
// Set the value of the input named 'parent'
|
||||
const parentInput = form.querySelector('input[name=parent]');
|
||||
|
||||
if (parentInput) {
|
||||
parentInput.value = ident;
|
||||
}
|
||||
|
||||
// Find the submit button and update its HTML
|
||||
const submitBtn = form.querySelector('button[type=submit]');
|
||||
|
||||
if (submitBtn) {
|
||||
const btnText = submitBtn.innerHTML.replace(/<[^>]*>/g, '').trim();
|
||||
submitBtn.innerHTML = '<i class="bi bi-arrow-90deg-left"></i> ' + btnText;
|
||||
@@ -1808,6 +1821,7 @@ function doreply(parent, ident, owner, hint) {
|
||||
// Check if the selection is inside the correct element
|
||||
let isInSel = false;
|
||||
const anchorNode = window.getSelection().anchorNode;
|
||||
|
||||
if (anchorNode) {
|
||||
let node = anchorNode.nodeType === 3 ? anchorNode.parentNode : anchorNode;
|
||||
while (node) {
|
||||
@@ -1821,15 +1835,26 @@ function doreply(parent, ident, owner, hint) {
|
||||
|
||||
modal.show();
|
||||
|
||||
modal_container.addEventListener('hide.bs.modal', event => {
|
||||
// move form back to where it was
|
||||
form_container.append(form);
|
||||
form_container.append(preview);
|
||||
});
|
||||
|
||||
// Set the textarea value
|
||||
const textarea = form.querySelector('textarea');
|
||||
|
||||
if (textarea) {
|
||||
let commentBody = localStorage.getItem('comment_body-' + ident);
|
||||
if (commentBody) {
|
||||
textarea.value = commentBody;
|
||||
}
|
||||
else {
|
||||
textarea.value = "@{" + owner + "}" + ((!isInSel || quote.length === 0) ? " " : "\n[quote]" + quote + "[/quote]\n");
|
||||
textarea.value = '@{' + owner + '} ';
|
||||
|
||||
if (quote && isInSel) {
|
||||
textarea.value += "\n[quote]" + quote + "[/quote]\n";
|
||||
}
|
||||
}
|
||||
|
||||
textarea.focus();
|
||||
@@ -2032,10 +2057,11 @@ function post_comment(id) {
|
||||
$('body').css('cursor', 'wait');
|
||||
$("#comment-preview-inp-" + id).val("0");
|
||||
|
||||
if(typeof conv_mode == typeof undefined)
|
||||
if (typeof conv_mode == typeof undefined) {
|
||||
conv_mode = '';
|
||||
}
|
||||
|
||||
var form_data = $("#comment-edit-form-" + id).serialize();
|
||||
const form_data = $("#comment-edit-form-" + id).serialize();
|
||||
|
||||
$.post(
|
||||
"item",
|
||||
@@ -2055,12 +2081,19 @@ function post_comment(id) {
|
||||
$("#comment-edit-text-" + id).val('').blur().attr('placeholder', aStr.comment);
|
||||
$('#wall-item-sub-thread-wrapper-' + data.thr_parent_id).append(data.html);
|
||||
|
||||
const comment = document.getElementById('wall-item-content-wrapper-' + data.id);
|
||||
comment.classList.add('item-highlight-fade');
|
||||
comment.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'center'
|
||||
});
|
||||
|
||||
updateRelativeTime('.autotime');
|
||||
$('body').css('cursor', 'unset');
|
||||
collapseHeight();
|
||||
commentBusy = false;
|
||||
|
||||
var tarea = document.getElementById("comment-edit-text-" + id);
|
||||
const tarea = document.getElementById("comment-edit-text-" + id);
|
||||
if (tarea) {
|
||||
commentClose(tarea, id);
|
||||
$(document).off( "click.commentOpen");
|
||||
|
||||
10
view/tpl/dirtagcloud.tpl
Normal file
10
view/tpl/dirtagcloud.tpl
Normal file
@@ -0,0 +1,10 @@
|
||||
<div class="dirtagblock widget">
|
||||
<h3>{{$title}}</h3>
|
||||
<div class="tags text-center">
|
||||
{{foreach $tags as $tag}}
|
||||
<span class="tag tag{{$tag.normalise}}">#</span><a href="{{$baseurl}}{{$tag.term}}" class="tag tag{{$tag.normalise}}" rel="nofollow">{{$tag.term}}</a>
|
||||
{{/foreach}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
10
view/tpl/tagcloud.tpl
Normal file
10
view/tpl/tagcloud.tpl
Normal file
@@ -0,0 +1,10 @@
|
||||
<div class="tagblock widget">
|
||||
<h3>{{$title}}</h3>
|
||||
<div class="tags text-center">
|
||||
{{foreach $tags as $tag}}
|
||||
<span class="tag{{$tag.2}}">#</span><a href="{{$baseurl}}{{$tag.0}}" class="tag{{$tag.2}}">{{$tag.0}}</a>
|
||||
{{/foreach}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user