diff --git a/database/cloud-server.mwb b/database/cloud-server.mwb index 2290574..851c7ba 100644 Binary files a/database/cloud-server.mwb and b/database/cloud-server.mwb differ diff --git a/src/application/controller/api/user/profile.php b/src/application/controller/api/user/profile.php new file mode 100644 index 0000000..922345a --- /dev/null +++ b/src/application/controller/api/user/profile.php @@ -0,0 +1,89 @@ + false, + 'message' => _('Internal server error'), + 'profile' => [] +]; + +if (isset($_SESSION['userName'])) { + + $userName = isset($_POST['userName']) ? Filter::userName($_POST['userName']) : $_SESSION['userName']; + + if ($userProfileVersions = $_twister->getDHT($userName, 'profile', 's')) { + + // Check user exists + if ($userId = $_modelUser->getUserId($userName)) { + + // Add DHT version if not exists + foreach ($userProfileVersions as $userProfileVersion) { + + if (!$_modelProfile->versionExists($userId, + $userProfileVersion['p']['height'], + $userProfileVersion['p']['seq'])) { + + $profile = $userProfileVersion['p']['v']; + + $_modelProfile->add($userId, + $userProfileVersion['p']['height'], + $userProfileVersion['p']['seq'], + $userProfileVersion['p']['time'], + + isset($profile['fullname']) ? $profile['fullname'] : '', + isset($profile['bio']) ? $profile['bio'] : '', + isset($profile['location']) ? $profile['location'] : '', + isset($profile['url']) ? $profile['url'] : '', + isset($profile['bitmessage']) ? $profile['bitmessage'] : '', + isset($profile['tox']) ? $profile['tox'] : ''); + } + } + } + + + // Get latest version available + if ($profileInfo = $_modelProfile->get($userId)) { + + $response = [ + 'success' => true, + 'message' => _('Profile successfully received'), + 'profile' => [ + 'userName' => $userName, + 'fullName' => $profileInfo['fullName'], + 'location' => $profileInfo['location'], + 'url' => $profileInfo['url'], + 'bitMessage' => $profileInfo['bitMessage'], + 'tox' => $profileInfo['tox'], + 'bio' => nl2br($profileInfo['bio']), + ] + ]; + + } else { + + $response = [ + 'success' => false, + 'message' => _('Profile data not available'), + 'profile' => [] + ]; + } + + } else { + + $response = [ + 'success' => false, + 'message' => _('Could not receive profile details'), + 'profile' => [] + ]; + + } + +} else { + + $response = [ + 'success' => false, + 'message' => _('Session expired. Please, reload the page.'), + 'profile' => [] + ]; +} + +header('Content-Type: application/json; charset=utf-8'); +echo json_encode($response); \ No newline at end of file diff --git a/src/application/model/profile.php b/src/application/model/profile.php new file mode 100644 index 0000000..e8101c3 --- /dev/null +++ b/src/application/model/profile.php @@ -0,0 +1,87 @@ +_db->prepare("SELECT * FROM `profile` + WHERE `userId` = ? + + ORDER BY `seq` DESC + LIMIT 1"); + + $query->execute([$userId]); + + return $query->fetch(); + + } catch (PDOException $e) { + + trigger_error($e->getMessage()); + return false; + } + } + + public function versionExists(int $userId, int $blockId, int $seq) { + + try { + + $query = $this->_db->prepare("SELECT COUNT(*) AS `total` FROM `profile` + WHERE `userId` = ? AND `blockId` = ? AND `seq` = ?"); + + $query->execute([$userId, $blockId, $seq]); + + return $query->fetch()['total']; + + } catch (PDOException $e) { + + trigger_error($e->getMessage()); + return false; + } + } + + public function add(int $userId, + int $blockId, + int $seq, + int $time, + string $fullName, + string $bio, + string $location, + string $url, + string $bitMessage, + string $tox) { + + try { + + $query = $this->_db->prepare("INSERT INTO `profile` SET `userId` = ?, + `blockId` = ?, + `seq` = ?, + `time` = ?, + `fullName` = ?, + `bio` = ?, + `location` = ?, + `url` = ?, + `bitMessage` = ?, + `tox` = ?"); + + $query->execute([$userId, + $blockId, + $seq, + $time, + $fullName, + $bio, + $location, + $url, + $bitMessage, + $tox]); + + return $this->_db->lastInsertId(); + + } catch (PDOException $e) { + + trigger_error($e->getMessage()); + return false; + } + } +} \ No newline at end of file diff --git a/src/bootstrap.php b/src/bootstrap.php index 3f2d658..170d137 100644 --- a/src/bootstrap.php +++ b/src/bootstrap.php @@ -6,6 +6,7 @@ require('config.php'); require(PROJECT_DIR . '/application/model/model.php'); require(PROJECT_DIR . '/application/model/block.php'); require(PROJECT_DIR . '/application/model/user.php'); +require(PROJECT_DIR . '/application/model/profile.php'); require(PROJECT_DIR . '/system/curl.php'); require(PROJECT_DIR . '/system/twister.php'); @@ -35,6 +36,14 @@ $_modelUser = new ModelUser( DB_PASSWORD ); +$_modelProfile = new ModelProfile( + DB_DATABASE, + DB_HOST, + DB_PORT, + DB_USER, + DB_PASSWORD +); + $_modelBlock = new ModelBlock( DB_DATABASE, DB_HOST, @@ -92,6 +101,9 @@ if (isset($_GET['_route_'])) { case 'api/user/random': require(PROJECT_DIR . '/application/controller/api/user/random.php'); break; + case 'api/user/profile': + require(PROJECT_DIR . '/application/controller/api/user/profile.php'); + break; // Multi-attribute pages default: diff --git a/src/public/css/template/default/module/following.css b/src/public/css/template/default/module/following.css index dbbaf06..5c3e8f4 100644 --- a/src/public/css/template/default/module/following.css +++ b/src/public/css/template/default/module/following.css @@ -1,7 +1,7 @@ .moduleFollowing .item { padding: 16px; margin: 0 2px 2px 2px; - color: #1c1d1e; + color: #fff; background: rgba(238, 238, 238, 0.08); border-radius: 3px; } @@ -23,7 +23,7 @@ .moduleFollowing .item .avatar { position: absolute; - top: 16px; + top: 18px; left: 16px; } @@ -36,7 +36,7 @@ .moduleFollowing .item .action { position: absolute; - top: 16px; + top: 13px; right: 16px; } @@ -57,4 +57,38 @@ padding-right: 32px; letter-spacing: 0.2px; font-size: 13px; +} + +.moduleFollowing .item .info .username { + margin-bottom: 8px; +} + +.moduleFollowing .item .info .username a { + font-weight: bold; +} + +.moduleFollowing .item .info .location { + margin-top: 4px; +} + +.moduleFollowing .item .info .bio { + font-style: italic; + margin-top: 4px; + color: #c3c8ce +} + +.moduleFollowing .item.active .info .bio { + color: #515457 +} + +.moduleFollowing .item .info .url, +.moduleFollowing .item .info .tox, +.moduleFollowing .item .info .bitMessage { + display: inline-block; + margin-right: 4px; + margin-top: 4px; +} + +.moduleFollowing .item .info .tox { + font-size: 10px } \ No newline at end of file diff --git a/src/public/js/module/following.js b/src/public/js/module/following.js index 289ce7b..31ec3dc 100644 --- a/src/public/js/module/following.js +++ b/src/public/js/module/following.js @@ -5,7 +5,8 @@ var ModuleFollowing = { append: function(list, userName) { $(list).append( $('
', { - 'class': 'item' + (userName == $(list).data('username') ? ' active' : '') + 'class': 'item' + (userName == $(list).data('username') ? ' active' : ''), + 'data-username': userName }).append( $('
', { 'class': 'avatar' @@ -23,9 +24,33 @@ var ModuleFollowing = { $('
', { 'class': 'info' }).append( - $('', { - 'href': 'people/' + userName - }).append(userName) + $('
', { + 'class': 'username' + }).append( + $('', { + 'href': 'people/' + userName + }).append(userName) + ) + ).append( + $('
', { + 'class': 'location' + }) + ).append( + $('
', { + 'class': 'bio' + }) + ).append( + $('
', { + 'class': 'url' + }) + ).append( + $('
', { + 'class': 'tox' + }) + ).append( + $('
', { + 'class': 'bitmessage' + }) ) ).append( $('
', { @@ -43,6 +68,36 @@ var ModuleFollowing = { } } }, + loadProfile: function(list, userName) { + $.ajax({ + url: 'api/user/profile', + type: 'POST', + data: { + userName: userName + }, + success: function (response) { + + if (response.success) { + + $(list).find('div[data-username="' + userName + '"] .username > a').html(response.profile.fullName ? response.profile.fullName : response.profile.userName); + $(list).find('div[data-username="' + userName + '"] .location').html(response.profile.location); + $(list).find('div[data-username="' + userName + '"] .url').html($('',{'href':response.profile.url,'class':'bi bi-link','title':'Website'})); + $(list).find('div[data-username="' + userName + '"] .bio').html(response.profile.bio); + $(list).find('div[data-username="' + userName + '"] .bitMessage').html(response.profile.bitMessage == '' ? '' : $('',{'href':'bitmessage:' + response.profile.bitMessage,'class':'bi bi-send','title':'BitMessage'})); + $(list).find('div[data-username="' + userName + '"] .tox').html(response.profile.tox == '' ? '' : $('',{'href':'tox:' + response.profile.tox,'class':'bi bi-chat-square-dots','title':'TOX'})); + + + } else { + + console.log(response.message); + + } + }, + error: function(jqXHR, textStatus, errorThrown) { + console.log(textStatus, errorThrown); + } + }); + }, load: function(list, reFresh) { $.ajax({ url: 'api/follow/get', @@ -57,11 +112,12 @@ var ModuleFollowing = { $(response.users).each(function() { ModuleFollowing.template.list.item.append(list, this.userName); + ModuleFollowing.loadProfile(list, this.userName); }); } else { - alert(response.message); + console.log(response.message); } }, @@ -88,7 +144,7 @@ var ModuleFollowing = { } else { - alert(response.message); + console.log(response.message); } },