longpoll api update, waiting list update, chat update, online status

This commit is contained in:
Michael Wain 2024-02-22 02:27:36 +03:00
parent 89fde1afc9
commit ff0fbe06ac
24 changed files with 1056 additions and 639 deletions

View File

@ -75,6 +75,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
</dependencies>
<build>

View File

@ -1,30 +1,233 @@
package com.alterdekim.game.component;
import com.alterdekim.game.dto.LongPollResult;
import com.alterdekim.game.dto.*;
import com.alterdekim.game.entities.Chat;
import com.alterdekim.game.entities.Room;
import com.alterdekim.game.entities.RoomPlayer;
import com.alterdekim.game.entities.User;
import com.alterdekim.game.service.*;
import com.alterdekim.game.util.Hash;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@Component
@Getter
@Slf4j
public class LongPoll {
private final BlockingQueue<LongPollingSession> longPollingQueue = new ArrayBlockingQueue<>(100);
private final Integer iterations = 6;
@Scheduled(fixedRate = 5000)
private final BlockingQueue<LongPollingSession> longPollingQueue = new ArrayBlockingQueue<>(100);
private final ConcurrentHashMap<Long, LongPollConfig> map = new ConcurrentHashMap<>();
@Autowired
private UserServiceImpl userService;
@Autowired
private ChatServiceImpl chatService;
@Autowired
private RoomServiceImpl roomService;
@Autowired
private RoomPlayerServiceImpl roomPlayerService;
@Autowired
private FriendServiceImpl friendService;
@Scheduled(fixedRate = 3000)
private void longPoll() {
getLongPollingQueue().removeIf(e -> e.getDeferredResult().isSetOrExpired());
roomService.clearEmptyRooms();
getMap().keySet().forEach(k -> {
if( (System.currentTimeMillis() - getMap().get(k).getLastRequest()) >= 60000 ) getMap().remove(k);
});
getLongPollingQueue().forEach(longPollingSession -> {
try {
longPollingSession.getDeferredResult().setResult(new LongPollResult());
if( !map.containsKey(longPollingSession.getUserId())) map.put(longPollingSession.getUserId(), new LongPollConfig(0L,new ArrayList<>(), 0, Hash.rnd(), new ArrayList<>(), System.currentTimeMillis()));
LongPollConfig config = map.get(longPollingSession.getUserId());
LongPollResult result = process(longPollingSession.getUserId(), config);
if( !result.getRooms().isEmpty() )
config.setRooms(result.getRooms().stream().filter(r -> r.getAction() == RoomResultState.ADD_CHANGE).map(r -> new RoomResult(r.getId(), r.getPlayerCount(), r.getPlayers())).collect(Collectors.toList()));
if( !result.getFriends().isEmpty() )
config.setFriends_online(result.getFriends().stream().filter(r -> r.getAction() == FriendState.ADD).map(r -> new UserResult(r.getId(), r.getUsername())).collect(Collectors.toList()));
config.setSession_pass(config.getSession_pass()+1);
if( !result.getFriends().isEmpty() || !result.getRooms().isEmpty() || !result.getMessages().isEmpty() || config.getSession_pass() >= iterations) {
longPollingSession.getDeferredResult().setResult(result);
config.setSession_pass(0);
}
map.put(longPollingSession.getUserId(), config);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
});
getLongPollingQueue().removeIf(e -> e.getDeferredResult().isSetOrExpired());
}
private LongPollResult process(Long userId, LongPollConfig config) {
userService.updateOnline(userId);
Integer onlineCount = userService.countByIsOnline();
List<Chat> results;
List<UserResult> users = new ArrayList<>();
List<RoomResult> clientRooms = config.getRooms();
List<RoomResultV2> roomResults = new ArrayList<>();
List<UserResult> clientFriends = config.getFriends_online();
List<FriendResult> friendsResult = new ArrayList<>();
results = chatService.getAfterLastChatId(config.getLast_chat_id());
if( !results.isEmpty() ) {
users = results.stream()
.map(Chat::getUserId)
.distinct()
.map(l -> userService.findById(l))
.map(u -> new UserResult(u.getId(), u.getUsername()))
.collect(Collectors.toList());
results = results.stream().peek(c -> {
String message = c.getMessage();
for (int i = 0; i < message.length(); i++) {
if (message.charAt(i) == '@') {
int u = message.substring(i).indexOf(' ') + i;
String username = message.substring(i + 1, u);
User user = userService.findByUsername(username);
if (user != null) {
Long uid = user.getId();
message = message.substring(0, i) + "<a href=\"/profile/" + uid + "\" class=\"chat-history-user\"><span class=\"_nick\">" + username + "</span></a>" + message.substring(u + 1);
} else {
message = message.substring(0, i) + username + message.substring(u + 1);
}
i = 0;
}
}
c.setMessage(message);
}).collect(Collectors.toList());
}
if( !clientRooms.isEmpty() ) {
List<RoomResult> rooms = roomService.getAllActive().stream()
.map( r -> new RoomResult(r.getId(), r.getPlayerCount(), roomPlayerService.findByRoomId(r.getId()).stream()
.map(p -> userService.findById(p.getUserId()))
.map(p -> new UserResult(p.getId(), p.getUsername()))
.collect(Collectors.toList())))
.collect(Collectors.toList());
if( !isEqualListRoom(rooms, clientRooms) ) {
List<RoomResult> rr = new ArrayList<>(rooms);
List<RoomResultV2> resultV2List = new ArrayList<>();
for( RoomResult r : clientRooms ) {
if( rooms.stream().noneMatch(t -> t.getId().longValue() == r.getId().longValue()) ) {
resultV2List.add(new RoomResultV2(RoomResultState.REMOVE, r.getId(), r.getPlayerCount(), r.getPlayers()));
} else {
RoomResult r1 = rooms.stream().filter( t -> t.getId().longValue() == r.getId().longValue()).findFirst().get();
if( !isEqual(r, r1) ) {
resultV2List.add(new RoomResultV2(RoomResultState.ADD_CHANGE, r1.getId(), r1.getPlayerCount(), r1.getPlayers()));
}
rr.remove(r1);
}
}
for( RoomResult r : rr ) {
resultV2List.add(new RoomResultV2(RoomResultState.ADD_CHANGE, r.getId(), r.getPlayerCount(), r.getPlayers()));
}
roomResults = resultV2List.stream().sorted(Comparator.comparingLong(RoomResultV2::getId)).collect(Collectors.toList());
} else {
roomResults = new ArrayList<>();
}
} else {
List<Room> rooms = roomService.getAllActive();
roomResults = rooms.stream()
.map( r -> new RoomResultV2(RoomResultState.ADD_CHANGE, r.getId(), r.getPlayerCount(), roomPlayerService.findByRoomId(r.getId()).stream()
.map(p -> userService.findById(p.getUserId()))
.map(p -> new UserResult(p.getId(), p.getUsername()))
.collect(Collectors.toList())))
.collect(Collectors.toList());
}
if( !clientFriends.isEmpty() ) {
List<UserResult> userResults = friendService.getFriendsOfUserId(userId)
.stream()
.map(id -> userService.findById(id))
.map(u -> new UserResult(u.getId(), u.getUsername()))
.filter(f -> getMap().keySet().stream().anyMatch(l -> l.longValue() == f.getId().longValue()))
.collect(Collectors.toList());
if( !isEqualListUser(userResults, clientFriends) ) {
List<UserResult> urr = new ArrayList<>(userResults);
List<FriendResult> fr = new ArrayList<>();
for( UserResult r : clientFriends ) {
if( userResults.stream().noneMatch(t -> t.getId().longValue() == r.getId().longValue()) ) {
fr.add(new FriendResult(FriendState.REMOVE, r.getId(), r.getUsername()));
} else {
UserResult r1 = userResults.stream().filter( t -> t.getId().longValue() == r.getId().longValue()).findFirst().get();
if( !isEqualUser(r, r1) ) {
fr.add(new FriendResult(FriendState.ADD, r1.getId(), r1.getUsername()));
}
urr.remove(r1);
}
}
for( UserResult r : urr ) {
fr.add(new FriendResult(FriendState.ADD, r.getId(), r.getUsername()));
}
friendsResult = fr.stream().sorted(Comparator.comparingLong(FriendResult::getId)).collect(Collectors.toList());
} else {
friendsResult = new ArrayList<>();
}
} else {
friendsResult = friendService.getFriendsOfUserId(userId)
.stream()
.map(id -> userService.findById(id))
.filter(f -> getMap().keySet().stream().anyMatch(l -> l.longValue() == f.getId().longValue()))
.map(f -> new FriendResult(FriendState.ADD, f.getId(), f.getUsername()))
.collect(Collectors.toList());
}
return new LongPollResult(onlineCount, results, users, roomResults, friendsResult);
}
private Boolean isEqual(RoomResult r1, RoomResult r2) {
return r1.getId().longValue() == r2.getId().longValue() &&
r1.getPlayerCount().intValue() == r2.getPlayerCount().intValue() &&
isEqualListUser(r1.getPlayers(), r2.getPlayers());
}
private Boolean isEqualUser(UserResult r1, UserResult r2) {
return r1.getId().longValue() == r2.getId().longValue() &&
r1.getUsername().equals(r2.getUsername());
}
private Boolean isEqualListRoom(List<RoomResult> r1, List<RoomResult> r2) {
r1 = r1.stream().sorted(Comparator.comparingLong(RoomResult::getId)).collect(Collectors.toList());
r2 = r2.stream().sorted(Comparator.comparingLong(RoomResult::getId)).collect(Collectors.toList());
if( r1.size() != r2.size() ) return false;
for( int i = 0; i < r1.size(); i++ ) {
if( !isEqual(r1.get(i), r2.get(i)) ) return false;
}
return true;
}
private Boolean isEqualListUser(List<UserResult> r1, List<UserResult> r2) {
r1 = r1.stream().sorted(Comparator.comparingLong(UserResult::getId)).collect(Collectors.toList());
r2 = r2.stream().sorted(Comparator.comparingLong(UserResult::getId)).collect(Collectors.toList());
if( r1.size() != r2.size() ) return false;
for( int i = 0; i < r1.size(); i++ ) {
if( r1.get(i).getId().longValue() != r2.get(i).getId().longValue() ||
!r1.get(i).getUsername().equals(r2.get(i).getUsername()) ) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,23 @@
package com.alterdekim.game.component;
import com.alterdekim.game.dto.RoomResult;
import com.alterdekim.game.dto.UserResult;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.List;
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class LongPollConfig {
private Long last_chat_id;
private List<RoomResult> rooms;
private Integer session_pass;
private String poll_token;
private List<UserResult> friends_online;
private Long lastRequest;
}

View File

@ -7,8 +7,7 @@ import org.springframework.web.context.request.async.DeferredResult;
@AllArgsConstructor
@Getter
public class LongPollingSession {
private Long last_chat_id;
private Long userId;
private DeferredResult<LongPollResult> deferredResult;
}

View File

@ -2,6 +2,7 @@ package com.alterdekim.game.controller;
import com.alterdekim.game.component.LongPoll;
import com.alterdekim.game.component.LongPollConfig;
import com.alterdekim.game.component.LongPollingSession;
import com.alterdekim.game.dto.*;
import com.alterdekim.game.entities.Chat;
@ -20,10 +21,9 @@ import org.springframework.web.context.request.async.DeferredResult;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Slf4j
@ -51,17 +51,6 @@ public class APIController {
@Autowired
private LongPoll longPoll;
@GetMapping("/api/v1/games/list")
public ResponseEntity<List<RoomResult>> gamesList() {
List<RoomResult> results = roomService.getAll()
.stream()
.map(room -> new RoomResult(room.getId(), room.getPlayerCount(), roomPlayerService.findByRoomId(room.getId()).stream()
.map(p -> userService.findById(p.getId()))
.map(p -> new UserResult(p.getId(), p.getUsername())).collect(Collectors.toList())))
.collect(Collectors.toList());
return ResponseEntity.ok(results);
}
@GetMapping("/api/v1/chat/history/{count}/")
public ResponseEntity<ChatResult> chatList(@PathVariable Integer count ) {
List<Chat> results = chatService.getLastChats(count);
@ -132,11 +121,24 @@ public class APIController {
return ResponseEntity.accepted().build();
}
@GetMapping("/async/notify/get/")
@PostMapping("/api/v1/rooms/create/")
public ResponseEntity<String> createRoom( @RequestParam("is_private") Boolean is_private,
@RequestParam("players_count") Integer players_count) {
if( !(players_count >= 2 && players_count <= 5) ) return ResponseEntity.badRequest().build();
Long id = roomService.createRoom(new Room(players_count, is_private, "0"));
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
Long userId = userService.findByUsername(((org.springframework.security.core.userdetails.User) auth.getPrincipal()).getUsername()).getId();
roomPlayerService.leaveByUserId(userId);
roomPlayerService.joinRoom(id, userId);
return ResponseEntity.accepted().build();
}
@PostMapping("/async/notify/get/")
@ResponseBody
public DeferredResult<LongPollResult> getNotify(@RequestParam("last_chat_id") Long last_chat_id,
@RequestParam("accessToken") String accessToken,
@RequestParam("uid") Long userId) {
@RequestParam("uid") Long userId,
@RequestParam("poll_token") String poll_token) {
try {
User u = userService.findById(userId);
if (u == null) return null;
@ -145,48 +147,22 @@ public class APIController {
} catch ( Exception e ) {
log.error(e.getMessage(), e);
}
if( poll_token.length() != 32 ) return null;
final DeferredResult<LongPollResult> deferredResult = new DeferredResult<>();
longPoll.getLongPollingQueue().add(new LongPollingSession(last_chat_id, deferredResult));
/*Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Long userId = userService.findByUsername(((org.springframework.security.core.userdetails.User) authentication.getPrincipal()).getUsername()).getId();
userService.updateOnline(userId);
Integer onlineCount = userService.countByIsOnline();
List<Chat> results = chatService.getAfterLastChatId(last_chat_id);
List<UserResult> users = results.stream()
.map(Chat::getUserId)
.distinct()
.map( l -> userService.findById(l) )
.map( u -> new UserResult(u.getId(), u.getUsername()) )
.collect(Collectors.toList());
results = results.stream().map( c -> {
String message = c.getMessage();
for( int i = 0; i < message.length(); i++ ) {
if( message.charAt(i) == '@' ) {
int u = message.substring(i).indexOf(' ') + i;
String username = message.substring(i+1, u);
User user = userService.findByUsername(username);
if( user != null ) {
Long uid = user.getId();
message = message.substring(0, i) + "<a href=\"/profile/" + uid + "\" class=\"chat-history-user\"><span class=\"_nick\">" + username + "</span></a>" + message.substring(u + 1);
} else {
message = message.substring(0, i) + username + message.substring(u + 1);
}
i = 0;
}
if( longPoll.getMap().containsKey(userId) ){
LongPollConfig c = longPoll.getMap().get(userId);
if( !c.getPoll_token().equals(poll_token) ) {
c = new LongPollConfig(last_chat_id, new ArrayList<>(), 0, poll_token, new ArrayList<>(), System.currentTimeMillis());
longPoll.getLongPollingQueue().removeIf(q -> q.getUserId().longValue() == userId.longValue());
}
c.setMessage(message);
return c;
}).collect(Collectors.toList());
// Room stuff
List<Room> rooms = roomService.getAllActive();
List<RoomResult> roomResults = rooms.stream()
.map( r -> new RoomResult(r.getId(), r.getPlayerCount(), roomPlayerService.findByRoomId(r.getId()).stream()
.map(p -> userService.findById(p.getId()))
.map(p -> new UserResult(p.getId(), p.getUsername())).collect(Collectors.toList())))
.collect(Collectors.toList());
return ResponseEntity.ok(new LongPollResult(onlineCount, results, users, roomResults));*/
c.setLast_chat_id(last_chat_id);
c.setSession_pass(0);
c.setLastRequest(System.currentTimeMillis());
longPoll.getMap().put(userId, c);
} else {
longPoll.getMap().put(userId, new LongPollConfig(last_chat_id, new ArrayList<>(), 0, poll_token, new ArrayList<>(), System.currentTimeMillis()));
}
longPoll.getLongPollingQueue().add(new LongPollingSession(userId, deferredResult));
return deferredResult;
}
}

View File

@ -31,7 +31,7 @@ public class StaticController {
User u = userService.findByUsername(((org.springframework.security.core.userdetails.User) authentication.getPrincipal()).getUsername());
Long userId = u.getId();
String apiKey = Hash.sha256((u.getId() + u.getUsername() + u.getPassword()).getBytes());
model.addAttribute("auth_obj", new AuthApiObject(apiKey, userId));
model.addAttribute("auth_obj", new AuthApiObject(apiKey, userId, Hash.rnd()));
} catch ( Exception e ) {
log.error(e.getMessage(), e);
}

View File

@ -10,4 +10,5 @@ import lombok.NoArgsConstructor;
public class AuthApiObject {
private String accessToken;
private Long uid;
private String poll_token;
}

View File

@ -0,0 +1,14 @@
package com.alterdekim.game.dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class FriendResult {
private FriendState action;
private Long id;
private String username;
}

View File

@ -0,0 +1,6 @@
package com.alterdekim.game.dto;
public enum FriendState {
ADD,
REMOVE
}

View File

@ -14,5 +14,6 @@ public class LongPollResult {
private Integer onlineCount;
private List<Chat> messages;
private List<UserResult> users;
private List<RoomResult> rooms;
private List<RoomResultV2> rooms;
private List<FriendResult> friends;
}

View File

@ -0,0 +1,6 @@
package com.alterdekim.game.dto;
public enum RoomResultState {
ADD_CHANGE,
REMOVE
}

View File

@ -0,0 +1,17 @@
package com.alterdekim.game.dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.List;
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class RoomResultV2 {
private RoomResultState action;
private Long id;
private Integer playerCount;
private List<UserResult> players;
}

View File

@ -0,0 +1,16 @@
package com.alterdekim.game.repository;
import com.alterdekim.game.entities.FriendStatus;
import com.alterdekim.game.entities.Room;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface FriendRepository extends JpaRepository<FriendStatus, Long> {
@Query(value = "SELECT IF(f.firstUserId = :userId, f.secondUserId, f.firstUserId) FROM FriendStatus f WHERE (f.firstUserId = :userId OR f.secondUserId = :userId) AND f.status = 2")
List<Long> getFriendsOfUserId(@Param("userId") Long userId);
}

View File

@ -3,11 +3,22 @@ package com.alterdekim.game.repository;
import com.alterdekim.game.entities.Room;
import com.alterdekim.game.entities.RoomPlayer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Repository
public interface RoomPlayerRepository extends JpaRepository<RoomPlayer, Long> {
List<RoomPlayer> findByRoomId(Long roomId);
@Query(value = "SELECT new RoomPlayer(r.id, r.roomId, r.userId) FROM RoomPlayer r WHERE r.roomId = :roomId ORDER BY r.userId ASC")
List<RoomPlayer> findByRoomId(@Param("roomId") Long roomId);
@Transactional
@Modifying
@Query(value = "DELETE FROM RoomPlayer r WHERE r.userId = :userId")
void deleteAllByUserId(@Param("userId") Long userId);
}

View File

@ -3,14 +3,22 @@ package com.alterdekim.game.repository;
import com.alterdekim.game.entities.Room;
import com.alterdekim.game.entities.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Repository
public interface RoomRepository extends JpaRepository<Room, Long> {
@Query(value = "SELECT r FROM Room r WHERE r.isPrivate = false")
@Query(value = "SELECT r FROM Room r WHERE r.isPrivate = false ORDER BY r.id ASC")
List<Room> findAllByActiveTrue();
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Modifying
@Query(value = "DELETE FROM room WHERE room.id NOT IN (SELECT t.room_id FROM (SELECT COUNT(id) as UID, room_id FROM room_player GROUP BY room_id) t)", nativeQuery = true)
void clearEmptyRooms();
}

View File

@ -0,0 +1,17 @@
package com.alterdekim.game.service;
import com.alterdekim.game.repository.FriendRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@AllArgsConstructor
public class FriendServiceImpl {
private final FriendRepository repository;
public List<Long> getFriendsOfUserId(Long userId) {
return repository.getFriendsOfUserId(userId);
}
}

View File

@ -24,4 +24,12 @@ public class RoomPlayerServiceImpl implements RoomPlayerService{
public List<RoomPlayer> findByRoomId(Long roomId) {
return repository.findByRoomId(roomId);
}
public void joinRoom(Long id, Long userId) {
repository.save(new RoomPlayer(id, userId));
}
public void leaveByUserId(Long userId) {
repository.deleteAllByUserId(userId);
}
}

View File

@ -5,6 +5,7 @@ import com.alterdekim.game.repository.RoomRepository;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class RoomServiceImpl implements RoomService {
@ -22,4 +23,16 @@ public class RoomServiceImpl implements RoomService {
public List<Room> getAllActive() {
return roomRepository.findAllByActiveTrue();
}
public Optional<Room> findById(Long id) {
return roomRepository.findById(id);
}
public Long createRoom(Room room) {
return roomRepository.save(room).getId();
}
public void clearEmptyRooms() {
roomRepository.clearEmptyRooms();
}
}

View File

@ -1,6 +1,9 @@
package com.alterdekim.game.util;
import java.security.MessageDigest;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Hash {
public static String sha256( byte[] b ) throws Exception {
@ -19,4 +22,12 @@ public class Hash {
}
return hexString.toString();
}
public static String rnd() {
return IntStream.generate(() -> new Random().nextInt(0, 62))
.limit(32)
.boxed()
.map(i -> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".charAt(i)+"")
.collect(Collectors.joining());
}
}

View File

@ -0,0 +1,414 @@
.grid {
display: grid !important;
grid-template-columns: repeat(12,1fr);
grid-column-gap: 25px;
}
.g-col-4 {
grid-column-end: span 4;
min-width: 0;
}
.g-col-8 {
grid-column-end: span 8;
min-width: 0;
}
.block {
display: block;
border-bottom: 2px solid rgba(0,0,0,.1);
border-radius: 5px;
padding-top: .1px;
padding-bottom: .1px;
width: 100%;
min-height: 1px;
background-color: #fff;
}
.container {
width: 1000px;
}
.title {
margin-bottom: 15px;
font-size: 18px;
margin-top: 20px;
margin-right: 20px;
margin-left: 20px;
}
.block-content {
justify-content: center;
display: flex;
margin-bottom: 15px;
}
.market {
height: 160px;
align-items: center;
justify-content: center;
display: flex;
}
.transparent-override {
background-color: transparent !important;
}
.text-glowing {
color: rgba(55, 188, 157, 1) !important;
}
.mission-one {
margin-top: 10px;
border-top: 1px solid #e9eaec;
padding: 10px;
}
.mission-target>span {
font-weight: 700;
}
.mission-block>span {
font-weight: 700;
}
.progress {
margin-top: 5px;
height: 7px;
}
.progress-bar {
background-color: rgba(55, 188, 157, 1) !important;
}
.mission-block, .mission-target {
font-size: 13px;
margin-top: 5px;
display: flex;
align-items: center;
gap: 0.3em;
}
.mission-text {
font-size: 13px;
}
.friend-search {
margin: 20px;
line-height: 1.6;
}
.empty-list-message {
text-align: center;
margin: 20px;
}
.empty-list-message>p {
font-size: 13px;
}
.title > span {
color: #a7adb5;
font-size: 14px;
}
.chat-history {
padding: 20px;
margin-bottom: 15px;
width: 100%;
height: 280px;
overflow-x: hidden;
overflow-y: scroll;
word-wrap: break-word;
}
#market-carousel {
width: 100%;
}
.carousel-title-text {
font-size: 19px;
font-weight: 700;
color: #fff;
}
.carousel-body-text {
margin-top: 10px;
font-size: 14px;
line-height: 20px;
color: #fff;
}
.carousel-item-body {
padding: 0 70px;
}
.carousel-item-background {
display: flex;
flex-direction: column;
justify-content: center;
}
.chat-history-one {
margin: 5px 0;
}
.chat-history-info {
display: inline-flex;
align-items: center;
margin-right: 5px;
color: #989aa4;
transform: translateY(1px);
}
.chat-history-user {
padding: 0 6px;
text-decoration: none;
background-color: #b9bac1;
border-radius: 5px;
}
.chat-history-user>._nick {
color: #fff;
font-weight: 600;
}
.chat-history-text {
margin-left: 5px;
}
.chat-history-one>* {
font-size: 14px;
vertical-align: middle;
line-height: 21px;
}
.chat-history-info>.time {
margin-right: 5px;
}
.message-input {
margin: 20px;
line-height: 1.6;
}
.games-room-one {
display: flex;
flex-flow: column nowrap;
position: relative;
border-top: 1px solid;
border-color: #e6e6e6;
}
.games-room-one-body {
padding: 10px 20px;
}
.games-room-one-body-head {
display: flex;
flex-flow: row nowrap;
height: 25px;
}
.games-room-one-body-head-info {
flex-grow: 999;
display: flex;
flex-flow: row nowrap;
gap: 10px;
}
.games-room-one-body-members {
display: flex;
flex-flow: row nowrap;
margin-top: 13px;
margin-bottom: 5px;
justify-content: center;
}
.games-room-one-body-members-one {
position: relative;
margin: 0 5px;
width: calc(20% - 2 * 5px);
}
.games-room-one-body-members-one-nick {
margin-top: 5px;
height: 21px;
text-align: center;
line-height: 21px;
white-space: nowrap;
}
.games-room-one-body-members-one-nick > a {
color: #656d78;
font-size: 14px;
}
.games-room-one-body-members-one-nick > span {
color: #656d78;
font-size: 14px;
text-decoration: none;
}
.games-room-one-body-members-one-avatar {
display: flex;
justify-content: center;
align-items: center;
position: relative;
margin: auto;
border-radius: 100%;
width: 75px;
height: 75px;
background: center/cover no-repeat;
font: 50px Ionicons;
}
.games-room-one-body-head-info > ._type > div {
font-size: 15px;
}
.games-room-one-body-head-info > ._with_wormhole > div {
font-size: 15px;
}
._slot_join {
cursor: pointer;
}
#waiting_list > .title {
align-items: center;
display: flex;
position: relative;
}
#waiting_list > .title > a {
position: absolute;
right: 0;
}
body.modal-open > :not(.modal) {
-webkit-filter: blur(3px);
-moz-filter: blur(3px);
-o-filter: blur(3px);
-ms-filter: blur(3px);
filter: blur(3px);
}
.game-creation-modal-modes {
background-color: #f7f7f7;
flex-shrink: 0;
border-radius: 5px 0 0 5px;
padding: 10px 15px 10px 10px;
width: 250px;
overflow: hidden;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.game-creation-modal-block {
flex-shrink: 0;
position: relative;
left: -5px;
border-radius: 5px;
padding: 20px 0;
width: 375px;
background-color: #fff;
box-shadow: 0 0 25px rgba(0,0,0,.1);
}
.game-creation-modal-body {
display: flex;
position: relative;
box-shadow: 0 0 100px rgba(0,0,0,.333);
border-radius: 5px;
width: 620px;
text-align: left;
}
.game-creation-modal-modes-one._regular._selected {
background: #8cc152;
}
.game-creation-modal-modes-one._selected {
color: #fff;
}
.game-creation-modal-modes-one {
border-radius: 5px;
padding: 10px 15px;
cursor: pointer;
}
.game-creation-modal-modes-one-title {
font-weight: 600;
font-size: 18px;
line-height: 21px;
}
.game-creation-modal-modes-one-subtitle {
margin-top: 4px;
font-size: 12px;
line-height: 15px;
opacity: .85;
}
.game-creation-modal-block-title {
margin-bottom: 10px;
font-weight: 600;
margin-top: 0;
font-size: 18px;
position: relative;
margin-left: 20px;
margin-right: 20px;
}
.game-creation-modal-block-subtitle {
margin-right: 20px;
margin-left: 20px;
margin-top: 10px;
margin-bottom: 10px;
font-size: 16px;
position: relative;
font-weight: 400;
}
.form-switch-game {
transform: scale(1.2);
margin-left: 3.5rem;
}
.form-check-input:checked {
background-color: #37bc9d;
border-color: #37bc9d;
}
#players-count-range, .players-range-value {
margin-left: 20px;
width: 80%;
}
.form-range::-webkit-slider-thumb {
background-color: #37bc9d;
}
.reply-button {
cursor: pointer;
}
.friend-one {
align-items: center;
display: flex;
justify-content: space-around;
padding: 10px;
}
.friend-one > span {
font-size: 14px;
}
.friend-one > ion-icon {
font-size: 18px;
color: #37bc9d;
cursor: pointer;
}

View File

@ -0,0 +1,110 @@
.navbar-brand-custom {
color: #ffffff;
}
.navbar-brand-custom:hover {
color: #ffffff;
}
.navbar {
background-color: #37bc9d;
}
.btn-outline-primary {
border-color: transparent;
color: #fff;
}
.btn-primary {
background-color: rgba(255,255,255,.85);
color: #37bc9d;
border-color: rgba(255,255,255,.85);
}
.btn-primary:hover {
background-color: #ffffff;
border-color: #ffffff;
color: #37bc9d;
}
.btn-outline-primary:hover {
background-color: rgba(255, 255, 255,0.25);
border-color: rgba(255, 255, 255,0.25);
}
.page-title {
font: 700 3.5em Montserrat;
color: #fff;
}
.page-title-small {
margin-top: .7em;
font: 500 1.32em/1.4em Montserrat;
color: #fff;
}
.main-billboard {
background-color: #37bc9d;
height: 700px;
text-align: center;
padding-top: 50px;
}
.main-button {
color: #5b5d67;
background-color: #fff;
border-color: #fff;
font: 600 1.5rem Montserrat;
padding: 0 0.9em;
height: 2.1em;
align-items: center;
display: inline-flex;
}
.main-button:hover {
color: #5b5d67;
background-color: rgba(255, 255, 255, 0.85);
border-color: rgba(255, 255, 255, 0.85);
font: 600 1.5rem Montserrat;
padding: 0 0.9em;
height: 2.1em;
align-items: center;
display: inline-flex;
}
.page-main-button {
margin-top: 25px;
}
.page-title-second {
margin-top: 1.25em;
margin-right: 0px;
margin-bottom: 1.25em;
margin-left: 0px;
font: 700 3.25em Montserrat;
color: #26272b;
text-align: center;
}
.billboard-img {
box-shadow: 0 0 100px rgba(0,0,0,.33);
width: 900px;
overflow: hidden;
pointer-events: none;
}
.billboard-container {
display: flex;
justify-content: center;
margin-top: 40px;
}
h4 {
margin: 0 0 .4em;
font: 700 2em Montserrat;
}
.col_text {
font-size: 1.1em;
text-align: left;
}

View File

@ -1,10 +1,119 @@
$.fn.pressEnter = function(fn) {
var isPollingActive = true;
function createRoom() {
let isprivate = $("#flexSwitchCheckDefault").is(':checked');
let playerscnt = $("#players-count-range").val();
$.ajax({
url: "/api/v1/rooms/create/",
data: {
is_private: isprivate,
players_count: playerscnt
},
method: "POST"
}).done(function(data) {
$("#game-creation-menu-modal").modal('hide');
});
}
function successPolling(data) {
console.log(data);
let onlineCount = data.onlineCount;
$(".chat-title").find("span").html(onlineCount + " online");
let messages = data.messages;
let users = data.users;
let rooms = data.rooms;
let friends = data.friends;
if( messages.length > 0 ) {
last_chat_id = messages[0].id;
}
for( let i = 0; i < messages.length; i++ ) {
let obj = messages[i];
let time = parseTime(obj.createdAt);
let username = findUser(users, obj.userId).username;
let userid = obj.userId;
let msgtext = obj.message;
let html = '<div class="chat-history-one"><div class="chat-history-info"><span class="time">'+time+'</span><ion-icon name="arrow-undo-outline" class="reply-button" data-userid="'+userid+'" data-username="'+username+'" onClick="replyButtonClicked(this)"></ion-icon></div><span><span class="chat-history-text chat-history-content-message"><span class="formatter"><a href="/profile/'+userid+'" class="chat-history-user"><span class="_nick">'+username+'</span></a><ion-icon name="remove-outline"></ion-icon><span>'+msgtext+'</span></span></span></span></div>';
$(".chat-history").append(html);
}
for( let i = 0; i < rooms.length; i++ ) {
let room = rooms[i];
if( room.action == 'ADD_CHANGE' ) {
let room_p_html = '';
for( let u = 0; u < room.players.length; u++ ) {
let room_player = room.players[u];
room_p_html += '<div class="games-room-one-body-members-one"><div class="games-room-one-body-members-one-avatar" style="background-image: url(&quot;https://i.dogecdn.wtf/7lurfckMFrYXm4gf&quot;);"><a href="/profile/'+room_player.id+'"></a><div class="_online"></div></div><div class="games-room-one-body-members-one-nick"><a href="/profile/'+room_player.id+'">'+room_player.username+'</a></div></div>';
}
for( let u = 0; u < (room.playerCount - room.players.length); u++ ) {
room_p_html += '<div class="games-room-one-body-members-one _slot_join"><div class="games-room-one-body-members-one-avatar"><ion-icon name="add-outline" style="color: #656d78;"></ion-icon></div><div class="games-room-one-body-members-one-nick"><span>Join</span></div></div>';
}
let room_html = '<div class="games-room-one" data-room-id="'+room.id+'"><div class="games-room-one-body"><div class="games-room-one-body-head"><div class="games-room-one-body-head-info"><div class="_type"><div>Game</div></div></div><div class="games-room-one-body-head-actions"></div></div><div class="games-room-one-body-members">'+room_p_html+'</div></div></div>';
let has_element = false;
$(".games-room-one").each(function() {
if( $(this).attr("data-room-id") == room.id ) {
$(this).replaceWith(room_html);
has_element = true;
}
});
if( !has_element ) {
$(".rooms-list").append(room_html);
}
} else if( room.action == 'REMOVE' ) {
$(".games-room-one").each(function() {
if( $(this).attr("data-room-id") == room.id ) {
$(this).remove();
}
});
}
}
for( let i = 0; i < friends.length; i++ ) {
let friend = friends[i];
if( friend.action == 'ADD' ) {
let fr_html = '<div class="friend-one" data-friend-id="'+friend.id+'"><a href="/profile/'+friend.id+'" class="navbar-btn"><img class="navbar-profile-img" src="https://avatars.githubusercontent.com/u/102559365?v=4"></a><span>'+friend.username+'</span><ion-icon name="person-add-outline" role="img" class="md hydrated"></ion-icon></div>';
$(".friends-online-list").append(fr_html);
} else if( friend.action == 'REMOVE' ) {
$(".friend-one").each(function() {
if( $(this).attr("data-friend-id") == friend.id ) {
$(this).remove();
}
});
}
}
var clh = $('#chat_list').find(".chat-history");
clh.scrollTop(clh.prop("scrollHeight"));
$("#chat_list").find(".chat-history").css("display", "");
$("#chat_list").find(".message-input").css("display", "");
$("#chat_list").find(".block-content").css("display", "none");
}
function pollServer() {
let accessToken = $("api-tag").attr("data-access-token");
let uid = $("api-tag").attr("data-uid");
let poll_token = $("api-tag").attr("data-poll-token");
if (isPollingActive) {
window.setTimeout(function () {
$.ajax({
url: "/async/notify/get/",
data: {
last_chat_id: last_chat_id,
accessToken: accessToken,
poll_token: poll_token,
uid: uid
},
method: "POST"
}).done(function(data) {
successPolling(data);
//SUCCESS LOGIC
pollServer();
});
}, 1500);
}
}
$.fn.pressEnter = function(fn) {
return this.each(function() {
$(this).bind('enterPress', fn);
$(this).keyup(function(e){
if(e.keyCode == 13)
{
$(this).keyup(function(e) {
if(e.keyCode == 13) {
$(this).trigger("enterPress");
}
})
@ -34,41 +143,6 @@ function replyButtonClicked(obj) {
$('#chat-message-input').val($('#chat-message-input').val() + " @" + username + "");
}
setInterval(function() {
let accessToken = $("api-tag").attr("data-access-token");
let uid = $("api-tag").attr("data-uid");
$.ajax({
url: "/async/notify/get/",
data: {
last_chat_id: last_chat_id,
accessToken: accessToken,
uid: uid
},
method: "GET"
}).done(function(data) {
console.log(data);
let onlineCount = data.onlineCount;
$(".chat-title").find("span").html(onlineCount + " online");
let messages = data.messages;
let users = data.users;
if( messages.length > 0 ) {
last_chat_id = messages[0].id;
}
for( let i = 0; i < messages.length; i++ ) {
let obj = messages[i];
let time = parseTime(obj.createdAt);
let username = findUser(users, obj.userId).username;
let userid = obj.userId;
let msgtext = obj.message;
let html = '<div class="chat-history-one"><div class="chat-history-info"><span class="time">'+time+'</span><ion-icon name="arrow-undo-outline" class="reply-button" data-userid="'+userid+'" data-username="'+username+'" onClick="replyButtonClicked(this)"></ion-icon></div><span><span class="chat-history-text chat-history-content-message"><span class="formatter"><a href="/profile/'+userid+'" class="chat-history-user"><span class="_nick">'+username+'</span></a><ion-icon name="remove-outline"></ion-icon><span>'+msgtext+'</span></span></span></span></div>';
$(".chat-history").append(html);
}
$("#chat_list").find(".chat-history").css("display", "");
$("#chat_list").find(".message-input").css("display", "");
$("#chat_list").find(".block-content").css("display", "none");
});
}, 5000);
$(document).ready(function() {
$("#players-count-range").on("input", function() {
$("label[for='players-count-range']").find("span").text($(this).val());
@ -86,13 +160,6 @@ $(document).ready(function() {
}
});
$.ajax({
url: "/api/v1/games/list",
method: "GET"
}).done(function(data) {
console.log(data);
});
// block-content
$.ajax({
@ -114,6 +181,8 @@ $(document).ready(function() {
let html = '<div class="chat-history-one"><div class="chat-history-info"><span class="time">'+time+'</span><ion-icon name="arrow-undo-outline" class="reply-button" data-userid="'+userid+'" data-username="'+username+'" onClick="replyButtonClicked(this)"></ion-icon></div><span><span class="chat-history-text chat-history-content-message"><span class="formatter"><a href="/profile/'+userid+'" class="chat-history-user"><span class="_nick">'+username+'</span></a><ion-icon name="remove-outline"></ion-icon><span>'+msgtext+'</span></span></span></span></div>';
$(".chat-history").append(html);
}
var clh = $('#chat_list').find(".chat-history");
clh.scrollTop(clh.prop("scrollHeight"));
$("#chat_list").find(".chat-history").css("display", "");
$("#chat_list").find(".message-input").css("display", "");
$("#chat_list").find(".block-content").css("display", "none");
@ -140,10 +209,8 @@ $(document).ready(function() {
$(".market").find("#market-carousel").css("display", "");
});
/*$.ajax({
url: "/api/v1/games/list",
method: "GET"
}).done(function(data) {
console.log(data);
});*/
pollServer();
$(".rooms-list").css("display", "");
$("#waiting_list").find(".block-content").css("display", "none");
});

View File

@ -2,406 +2,8 @@
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<th:block th:insert="~{fragments/head}"></th:block>
<style>
.grid {
display: grid !important;
grid-template-columns: repeat(12,1fr);
grid-column-gap: 25px;
}
.g-col-4 {
grid-column-end: span 4;
min-width: 0;
}
.g-col-8 {
grid-column-end: span 8;
min-width: 0;
}
.block {
display: block;
border-bottom: 2px solid rgba(0,0,0,.1);
border-radius: 5px;
padding-top: .1px;
padding-bottom: .1px;
width: 100%;
min-height: 1px;
background-color: #fff;
}
.container {
width: 1000px;
}
.title {
margin-bottom: 15px;
font-size: 18px;
margin-top: 20px;
margin-right: 20px;
margin-left: 20px;
}
.block-content {
justify-content: center;
display: flex;
margin-bottom: 15px;
}
.market {
height: 160px;
align-items: center;
justify-content: center;
display: flex;
}
.transparent-override {
background-color: transparent !important;
}
.text-glowing {
color: rgba(55, 188, 157, 1) !important;
}
.mission-one {
margin-top: 10px;
border-top: 1px solid #e9eaec;
padding: 10px;
}
.mission-target>span {
font-weight: 700;
}
.mission-block>span {
font-weight: 700;
}
.progress {
margin-top: 5px;
height: 7px;
}
.progress-bar {
background-color: rgba(55, 188, 157, 1) !important;
}
.mission-block, .mission-target {
font-size: 13px;
margin-top: 5px;
display: flex;
align-items: center;
gap: 0.3em;
}
.mission-text {
font-size: 13px;
}
.friend-search {
margin: 20px;
line-height: 1.6;
}
.empty-list-message {
text-align: center;
margin: 20px;
}
.empty-list-message>p {
font-size: 13px;
}
.title > span {
color: #a7adb5;
font-size: 14px;
}
.chat-history {
padding: 20px;
margin-bottom: 15px;
width: 100%;
height: 280px;
overflow-x: hidden;
overflow-y: scroll;
word-wrap: break-word;
}
#market-carousel {
width: 100%;
}
.carousel-title-text {
font-size: 19px;
font-weight: 700;
color: #fff;
}
.carousel-body-text {
margin-top: 10px;
font-size: 14px;
line-height: 20px;
color: #fff;
}
.carousel-item-body {
padding: 0 70px;
}
.carousel-item-background {
display: flex;
flex-direction: column;
justify-content: center;
}
.chat-history-one {
margin: 5px 0;
}
.chat-history-info {
display: inline-flex;
align-items: center;
margin-right: 5px;
color: #989aa4;
transform: translateY(1px);
}
.chat-history-user {
padding: 0 6px;
text-decoration: none;
background-color: #b9bac1;
border-radius: 5px;
}
.chat-history-user>._nick {
color: #fff;
font-weight: 600;
}
.chat-history-text {
margin-left: 5px;
}
.chat-history-one>* {
font-size: 14px;
vertical-align: middle;
line-height: 21px;
}
.chat-history-info>.time {
margin-right: 5px;
}
.message-input {
margin: 20px;
line-height: 1.6;
}
.games-room-one {
display: flex;
flex-flow: column nowrap;
position: relative;
border-top: 1px solid;
border-color: #e6e6e6;
}
.games-room-one-body {
padding: 10px 20px;
}
.games-room-one-body-head {
display: flex;
flex-flow: row nowrap;
height: 25px;
}
.games-room-one-body-head-info {
flex-grow: 999;
display: flex;
flex-flow: row nowrap;
gap: 10px;
}
.games-room-one-body-members {
display: flex;
flex-flow: row nowrap;
margin-top: 13px;
margin-bottom: 5px;
justify-content: center;
}
.games-room-one-body-members-one {
position: relative;
margin: 0 5px;
width: calc(20% - 2 * 5px);
}
.games-room-one-body-members-one-nick {
margin-top: 5px;
height: 21px;
text-align: center;
line-height: 21px;
white-space: nowrap;
}
.games-room-one-body-members-one-nick > a {
color: #656d78;
font-size: 14px;
}
.games-room-one-body-members-one-nick > span {
color: #656d78;
font-size: 14px;
text-decoration: none;
}
.games-room-one-body-members-one-avatar {
display: flex;
justify-content: center;
align-items: center;
position: relative;
margin: auto;
border-radius: 100%;
width: 75px;
height: 75px;
background: center/cover no-repeat;
font: 50px Ionicons;
}
.games-room-one-body-head-info > ._type > div {
font-size: 15px;
}
.games-room-one-body-head-info > ._with_wormhole > div {
font-size: 15px;
}
._slot_join {
cursor: pointer;
}
#waiting_list > .title {
align-items: center;
display: flex;
position: relative;
}
#waiting_list > .title > a {
position: absolute;
right: 0;
}
body.modal-open > :not(.modal) {
-webkit-filter: blur(3px);
-moz-filter: blur(3px);
-o-filter: blur(3px);
-ms-filter: blur(3px);
filter: blur(3px);
}
.game-creation-modal-modes {
background-color: #f7f7f7;
flex-shrink: 0;
border-radius: 5px 0 0 5px;
padding: 10px 15px 10px 10px;
width: 250px;
overflow: hidden;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.game-creation-modal-block {
flex-shrink: 0;
position: relative;
left: -5px;
border-radius: 5px;
padding: 20px 0;
width: 375px;
background-color: #fff;
box-shadow: 0 0 25px rgba(0,0,0,.1);
}
.game-creation-modal-body {
display: flex;
position: relative;
box-shadow: 0 0 100px rgba(0,0,0,.333);
border-radius: 5px;
width: 620px;
text-align: left;
}
.game-creation-modal-modes-one._regular._selected {
background: #8cc152;
}
.game-creation-modal-modes-one._selected {
color: #fff;
}
.game-creation-modal-modes-one {
border-radius: 5px;
padding: 10px 15px;
cursor: pointer;
}
.game-creation-modal-modes-one-title {
font-weight: 600;
font-size: 18px;
line-height: 21px;
}
.game-creation-modal-modes-one-subtitle {
margin-top: 4px;
font-size: 12px;
line-height: 15px;
opacity: .85;
}
.game-creation-modal-block-title {
margin-bottom: 10px;
font-weight: 600;
margin-top: 0;
font-size: 18px;
position: relative;
margin-left: 20px;
margin-right: 20px;
}
.game-creation-modal-block-subtitle {
margin-right: 20px;
margin-left: 20px;
margin-top: 10px;
margin-bottom: 10px;
font-size: 16px;
position: relative;
font-weight: 400;
}
.form-switch-game {
transform: scale(1.2);
margin-left: 3.5rem;
}
.form-check-input:checked {
background-color: #37bc9d;
border-color: #37bc9d;
}
#players-count-range, .players-range-value {
margin-left: 20px;
width: 80%;
}
.form-range::-webkit-slider-thumb {
background-color: #37bc9d;
}
.reply-button {
cursor: pointer;
}
</style>
<api-tag th:data-access-token="${auth_obj.accessToken}" th:data-uid="${auth_obj.uid}"></api-tag>
<link rel="stylesheet" href="/static/css/games.css"/>
<api-tag th:data-access-token="${auth_obj.accessToken}" th:data-uid="${auth_obj.uid}" th:data-poll-token="${auth_obj.poll_token}"></api-tag>
</head>
<body>
<th:block th:insert="~{fragments/navbar}"></th:block>
@ -425,7 +27,7 @@
<label class="form-check-label" for="flexSwitchCheckDefault">Private room</label>
</div>
<div style="display: flex; justify-content: center;">
<button class="btn btn-primary navbar-btn">
<button class="btn btn-primary navbar-btn" onClick="createRoom()">
<span>Start</span>
</button>
</div>
@ -484,15 +86,15 @@
<span class="visually-hidden">Loading...</span>
</div>
</div>
<!--<div>
<div class="friends-online-list" style="display: none;">
<div class="friend-search">
<input type="text" class="friend-search-input form-control" placeholder="Search friends">
</div>
<div class="empty-list-message">
<!--<div class="empty-list-message">
<p>No friends online.</p>
</div>
</div>-->
</div>-->
</div>
</div>
</div>
<div class="g-col-8">
@ -559,8 +161,8 @@
<ion-icon name="dice-outline"></ion-icon>
<span>Create game</span>
</a></div>
<!--<div class="rooms-list">
<div class="games-room-one">
<div class="rooms-list" style="display: none">
<!--<div class="games-room-one">
<div class="games-room-one-body">
<div class="games-room-one-body-head">
<div class="games-room-one-body-head-info">
@ -620,8 +222,8 @@
</div>
</div>
</div>
</div>
</div>-->
</div>-->
</div>
<div class="block-content">
<div class="spinner-grow text-glowing" role="status">
<span class="visually-hidden">Loading...</span>

View File

@ -2,118 +2,7 @@
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<th:block th:insert="~{fragments/head}"></th:block>
<style>
.navbar-brand-custom {
color: #ffffff;
}
.navbar-brand-custom:hover {
color: #ffffff;
}
.navbar {
background-color: #37bc9d;
}
.btn-outline-primary {
border-color: transparent;
color: #fff;
}
.btn-primary {
background-color: rgba(255,255,255,.85);
color: #37bc9d;
border-color: rgba(255,255,255,.85);
}
.btn-primary:hover {
background-color: #ffffff;
border-color: #ffffff;
color: #37bc9d;
}
.btn-outline-primary:hover {
background-color: rgba(255, 255, 255,0.25);
border-color: rgba(255, 255, 255,0.25);
}
.page-title {
font: 700 3.5em Montserrat;
color: #fff;
}
.page-title-small {
margin-top: .7em;
font: 500 1.32em/1.4em Montserrat;
color: #fff;
}
.main-billboard {
background-color: #37bc9d;
height: 700px;
text-align: center;
padding-top: 50px;
}
.main-button {
color: #5b5d67;
background-color: #fff;
border-color: #fff;
font: 600 1.5rem Montserrat;
padding: 0 0.9em;
height: 2.1em;
align-items: center;
display: inline-flex;
}
.main-button:hover {
color: #5b5d67;
background-color: rgba(255, 255, 255, 0.85);
border-color: rgba(255, 255, 255, 0.85);
font: 600 1.5rem Montserrat;
padding: 0 0.9em;
height: 2.1em;
align-items: center;
display: inline-flex;
}
.page-main-button {
margin-top: 25px;
}
.page-title-second {
margin-top: 1.25em;
margin-right: 0px;
margin-bottom: 1.25em;
margin-left: 0px;
font: 700 3.25em Montserrat;
color: #26272b;
text-align: center;
}
.billboard-img {
box-shadow: 0 0 100px rgba(0,0,0,.33);
width: 900px;
overflow: hidden;
pointer-events: none;
}
.billboard-container {
display: flex;
justify-content: center;
margin-top: 40px;
}
h4 {
margin: 0 0 .4em;
font: 700 2em Montserrat;
}
.col_text {
font-size: 1.1em;
text-align: left;
}
</style>
<link rel="stylesheet" href="/static/css/index.css">
</head>
<body>
<th:block th:insert="~{fragments/navbar}"></th:block>