mirror of
https://github.com/Linloir/Simple-TCP-Client.git
synced 2025-12-17 00:38:11 +08:00
Bug Fix
This commit is contained in:
parent
e7f690159c
commit
84fe935fcd
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 14:03:56
|
||||
* @LastEditTime : 2022-10-17 17:43:55
|
||||
* @LastEditTime : 2022-10-18 11:25:04
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -9,7 +9,6 @@ import 'dart:async';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:open_file/open_file.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tcp_client/chat/cubit/chat_state.dart';
|
||||
import 'package:tcp_client/chat/model/chat_history.dart';
|
||||
@ -158,7 +157,6 @@ class ChatCubit extends Cubit<ChatState> {
|
||||
response as ForwardMessageResponse;
|
||||
if(response.message.senderID == userID || response.message.recieverID == userID) {
|
||||
// Message storage will be handled by home bloc listener
|
||||
// addMessage(response.message);
|
||||
//Emit new state
|
||||
var newHistory = ChatHistory(
|
||||
message: response.message,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-14 21:57:05
|
||||
* @LastEditTime : 2022-10-14 22:55:16
|
||||
* @LastEditTime : 2022-10-18 11:25:09
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -12,8 +12,6 @@ import 'package:tcp_client/chat/cubit/chat_cubit.dart';
|
||||
import 'package:tcp_client/chat/view/input_box/cubit/input_state.dart';
|
||||
import 'package:tcp_client/chat/view/input_box/model/input.dart';
|
||||
import 'package:tcp_client/repositories/common_models/message.dart';
|
||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
||||
|
||||
class MessageInputCubit extends Cubit<MessageInputState> {
|
||||
MessageInputCubit({
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-14 17:54:30
|
||||
* @LastEditTime : 2022-10-15 00:27:39
|
||||
* @LastEditTime : 2022-10-18 11:25:12
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -16,7 +16,6 @@ import 'package:tcp_client/chat/view/input_box/cubit/input_cubit.dart';
|
||||
import 'package:tcp_client/chat/view/input_box/cubit/input_state.dart';
|
||||
import 'package:tcp_client/chat/view/input_box/model/input.dart';
|
||||
import 'package:tcp_client/repositories/common_models/message.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/models/tcp_request.dart';
|
||||
|
||||
class InputBox extends StatelessWidget {
|
||||
InputBox({super.key});
|
||||
@ -29,9 +28,11 @@ class InputBox extends StatelessWidget {
|
||||
create:(context) => MessageInputCubit(
|
||||
chatCubit: context.read<ChatCubit>()
|
||||
),
|
||||
child: SizedBox(
|
||||
height: 64,
|
||||
child: Container(
|
||||
// height: 64,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: BlocListener<MessageInputCubit, MessageInputState>(
|
||||
@ -39,16 +40,29 @@ class InputBox extends StatelessWidget {
|
||||
listener: (context, state) {
|
||||
_controller.clear();
|
||||
},
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(maxHeight: 120),
|
||||
child: Builder(
|
||||
builder: (context) => TextField(
|
||||
controller: _controller,
|
||||
onChanged: (value) {
|
||||
context.read<MessageInputCubit>().onInputChange(MessageInput.dirty(value));
|
||||
},
|
||||
maxLines: null,
|
||||
decoration: const InputDecoration(
|
||||
border: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
width: 1.0
|
||||
)
|
||||
),
|
||||
hintText: 'Input message here'
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8.0,),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
var chatCubit = context.read<ChatCubit>();
|
||||
@ -66,8 +80,9 @@ class InputBox extends StatelessWidget {
|
||||
}
|
||||
});
|
||||
},
|
||||
icon: const Icon(Icons.attach_file_rounded)
|
||||
icon: Icon(Icons.attach_file_rounded, color: Colors.grey[700],)
|
||||
),
|
||||
const SizedBox(width: 8.0,),
|
||||
BlocBuilder<MessageInputCubit, MessageInputState>(
|
||||
builder:(context, state) {
|
||||
return IconButton(
|
||||
@ -75,6 +90,7 @@ class InputBox extends StatelessWidget {
|
||||
context.read<MessageInputCubit>().onSubmission();
|
||||
} : null,
|
||||
icon: const Icon(Icons.send_rounded),
|
||||
color: state.status == FormzStatus.valid ? Colors.blue : Colors.grey[400],
|
||||
);
|
||||
},
|
||||
)
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 14:02:28
|
||||
* @LastEditTime : 2022-10-17 17:00:45
|
||||
* @LastEditTime : 2022-10-17 19:26:13
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:tcp_client/home/cubit/home_state.dart';
|
||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/models/tcp_response.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
||||
|
||||
class HomeCubit extends Cubit<HomeState> {
|
||||
@ -20,11 +23,13 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
pageController.addListener(() {
|
||||
emit(state.copyWith(page: HomePagePosition.fromValue((pageController.page ?? 0).round())));
|
||||
});
|
||||
subscription = tcpRepository.responseStreamBroadcast.listen(_onTCPResponse);
|
||||
}
|
||||
|
||||
final LocalServiceRepository localServiceRepository;
|
||||
final TCPRepository tcpRepository;
|
||||
final PageController pageController;
|
||||
late final StreamSubscription subscription;
|
||||
|
||||
void switchPage(HomePagePosition newPage) {
|
||||
pageController.animateToPage(
|
||||
@ -33,4 +38,28 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
curve: Curves.easeInOutCubicEmphasized
|
||||
);
|
||||
}
|
||||
|
||||
void _onTCPResponse(TCPResponse response) {
|
||||
switch(response.type) {
|
||||
case TCPResponseType.forwardMessage: {
|
||||
response as ForwardMessageResponse;
|
||||
localServiceRepository.storeMessages([response.message]);
|
||||
break;
|
||||
}
|
||||
case TCPResponseType.fetchMessage: {
|
||||
response as FetchMessageResponse;
|
||||
localServiceRepository.storeMessages(response.messages);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() {
|
||||
subscription.cancel();
|
||||
return super.close();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-12 23:36:07
|
||||
* @LastEditTime : 2022-10-17 17:35:05
|
||||
* @LastEditTime : 2022-10-18 11:25:18
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -18,8 +18,7 @@ class ContactPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
child: BlocBuilder<ContactCubit, ContactState>(
|
||||
return BlocBuilder<ContactCubit, ContactState>(
|
||||
builder: (context, state) {
|
||||
var indexedData = state.indexedData;
|
||||
return AzListView(
|
||||
@ -50,7 +49,6 @@ class ContactPage extends StatelessWidget {
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 14:02:00
|
||||
* @LastEditTime : 2022-10-17 17:19:50
|
||||
* @LastEditTime : 2022-10-18 11:25:32
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:tcp_client/chat/chat_page.dart';
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-12 23:48:54
|
||||
* @LastEditTime : 2022-10-15 01:01:48
|
||||
* @LastEditTime : 2022-10-18 11:25:36
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:tcp_client/repositories/common_models/message.dart';
|
||||
import 'package:tcp_client/repositories/common_models/userinfo.dart';
|
||||
|
||||
class MessageInfo extends Equatable {
|
||||
final Message? message;
|
||||
|
||||
@ -1,19 +1,16 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 13:17:52
|
||||
* @LastEditTime : 2022-10-17 17:18:22
|
||||
* @LastEditTime : 2022-10-18 11:25:40
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:tcp_client/chat/chat_page.dart';
|
||||
import 'package:tcp_client/common/avatar/avatar.dart';
|
||||
import 'package:tcp_client/common/username/username.dart';
|
||||
import 'package:tcp_client/repositories/common_models/message.dart';
|
||||
import 'package:tcp_client/repositories/common_models/userinfo.dart';
|
||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
||||
import 'package:tcp_client/repositories/tcp_repository/tcp_repository.dart';
|
||||
import 'package:tcp_client/repositories/user_repository/user_repository.dart';
|
||||
@ -110,6 +107,8 @@ class MessageTile extends StatelessWidget {
|
||||
child: IgnorePointer(
|
||||
child: Text(
|
||||
message?.contentDecoded ?? '',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-14 10:54:57
|
||||
* @LastEditTime : 2022-10-14 11:44:12
|
||||
* @LastEditTime : 2022-10-17 20:51:45
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -36,6 +36,7 @@ class LogOutCubit extends Cubit<LogOutStatus> {
|
||||
}
|
||||
|
||||
void onLogout() async {
|
||||
emit(LogOutStatus.processing);
|
||||
tcpRepository.pushRequest(LogoutRequest(token: (await SharedPreferences.getInstance()).getInt('token')));
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-12 09:56:04
|
||||
* @LastEditTime : 2022-10-14 16:47:04
|
||||
* @LastEditTime : 2022-10-17 21:11:30
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -22,7 +22,11 @@ class InitializationCubit extends Cubit<InitializationState> {
|
||||
TCPRepository? tcpRepository;
|
||||
LocalServiceRepository? localServiceRepository;
|
||||
Future(() async {
|
||||
localServiceRepository = await LocalServiceRepository.create(databaseFilePath: '${(await getApplicationDocumentsDirectory()).path}/.data/database.db');
|
||||
localServiceRepository = await LocalServiceRepository.create(
|
||||
databaseFilePath: '${
|
||||
(await getApplicationDocumentsDirectory()).path
|
||||
}/LChatClient/.data/database.db'
|
||||
);
|
||||
}).then((_) {
|
||||
emit(state.copyWith(
|
||||
databaseStatus: InitializationStatus.done,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-11 10:56:02
|
||||
* @LastEditTime : 2022-10-17 13:01:35
|
||||
* @LastEditTime : 2022-10-18 11:27:15
|
||||
* @Description : Local Service Repository
|
||||
*/
|
||||
|
||||
@ -133,20 +133,30 @@ class LocalServiceRepository {
|
||||
}
|
||||
|
||||
Future<List<Message>> findMessages({required String pattern}) async {
|
||||
if(pattern.isEmpty) {
|
||||
return [];
|
||||
}
|
||||
// Obtain shared preferences.
|
||||
final pref = await SharedPreferences.getInstance();
|
||||
// Get user info from preferences
|
||||
var currentUserID = pref.getInt('userid');
|
||||
var alikeMessages = await _database.query(
|
||||
var rawMessages = await _database.query(
|
||||
'msgs',
|
||||
where: 'userid = ? or targetid = ?',
|
||||
where: '(userid = ? or targetid = ?)',
|
||||
whereArgs: [
|
||||
currentUserID, currentUserID
|
||||
],
|
||||
orderBy: 'timestamp desc',
|
||||
limit: 100
|
||||
);
|
||||
return alikeMessages.map((e) => Message.fromJSONObject(jsonObject: e)).toList();
|
||||
List<Message> alikeMessages = [];
|
||||
for(var rawMessage in rawMessages) {
|
||||
var message = Message.fromJSONObject(jsonObject: rawMessage);
|
||||
if(message.contentDecoded.contains(pattern)) {
|
||||
alikeMessages.add(message);
|
||||
}
|
||||
}
|
||||
return alikeMessages;
|
||||
}
|
||||
|
||||
//Find the most recent message of given users
|
||||
@ -266,7 +276,7 @@ class LocalServiceRepository {
|
||||
conflictAlgorithm: ConflictAlgorithm.replace
|
||||
);
|
||||
} catch (err) {
|
||||
print(err);
|
||||
//TODO: Log the err
|
||||
}
|
||||
//Clear temp file
|
||||
tempFile.file.delete();
|
||||
@ -318,7 +328,19 @@ class LocalServiceRepository {
|
||||
}
|
||||
|
||||
Future<UserInfo?> fetchUserInfoViaUsername({required String username}) async {
|
||||
|
||||
var result = await _database.query(
|
||||
'users',
|
||||
where: 'username = ?',
|
||||
whereArgs: [
|
||||
username
|
||||
]
|
||||
);
|
||||
if(result.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return UserInfo.fromJSONObject(jsonObject: result[0]);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Message?> fetchMessage({required String msgmd5}) async {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-11 09:42:05
|
||||
* @LastEditTime : 2022-10-15 16:50:16
|
||||
* @LastEditTime : 2022-10-18 11:27:46
|
||||
* @Description : TCP repository
|
||||
*/
|
||||
|
||||
@ -25,13 +25,26 @@ class TCPRepository {
|
||||
required String remoteAddress,
|
||||
required int remotePort
|
||||
}): _socket = socket, _remoteAddress = remoteAddress, _remotePort = remotePort {
|
||||
_socket.listen(_pullResponse);
|
||||
Future(() async {
|
||||
try{
|
||||
await for(var response in _socket) {
|
||||
_pullResponse(response);
|
||||
}
|
||||
} catch(e) {
|
||||
_socket.close();
|
||||
}
|
||||
// _responseRawStreamController.close();
|
||||
// _payloadPullStreamController.close();
|
||||
// _payloadRawStreamController.close();
|
||||
// _responseStreamController.close();
|
||||
// _requestStreamController.close();
|
||||
});
|
||||
//This future never ends, would that be bothersome?
|
||||
Future(() async {
|
||||
await for(var request in _requestStreamController.stream) {
|
||||
await _socket.addStream(request.stream);
|
||||
}
|
||||
});
|
||||
}).onError((error, stackTrace) {_socket.close();});
|
||||
Future(() async {
|
||||
var responseQueue = StreamQueue(_responseRawStreamController.stream);
|
||||
var payloadQueue = StreamQueue(_payloadRawStreamController.stream);
|
||||
@ -42,7 +55,7 @@ class TCPRepository {
|
||||
}
|
||||
responseQueue.cancel();
|
||||
payloadQueue.cancel();
|
||||
});
|
||||
}).onError((error, stackTrace) {_socket.close();});
|
||||
}
|
||||
|
||||
static Future<TCPRepository> create({
|
||||
@ -75,6 +88,9 @@ class TCPRepository {
|
||||
//Byte length for subsequent data of the json object
|
||||
int payloadLength = 0;
|
||||
|
||||
//Temp filename counter
|
||||
int _fileCounter = 0;
|
||||
|
||||
//Construct a stream which emits events on intact requests
|
||||
final StreamController<List<int>> _responseRawStreamController = StreamController();
|
||||
final StreamController<File> _payloadRawStreamController = StreamController();
|
||||
@ -147,9 +163,11 @@ class TCPRepository {
|
||||
Future(() async {
|
||||
var documentDirectory = await getApplicationDocumentsDirectory();
|
||||
//Create temp file to read payload (might be huge)
|
||||
Directory('${documentDirectory.path}/ChatClient').createSync();
|
||||
Directory('${documentDirectory.path}/ChatClient/.tmp').createSync();
|
||||
var tempFile = File('${documentDirectory.path}/ChatClient/.tmp/${DateTime.now().microsecondsSinceEpoch}')..createSync();
|
||||
Directory('${documentDirectory.path}/LChatClient').createSync();
|
||||
Directory('${documentDirectory.path}/LChatClient/.tmp').createSync();
|
||||
var tempFile = File('${documentDirectory.path}/LChatClient/.tmp/${DateTime.now().microsecondsSinceEpoch}$_fileCounter')..createSync();
|
||||
_fileCounter += 1;
|
||||
_fileCounter %= 10;
|
||||
await for(var data in payloadPullStream) {
|
||||
await tempFile.writeAsBytes(data, mode: FileMode.append, flush: true);
|
||||
}
|
||||
@ -342,10 +360,5 @@ class TCPRepository {
|
||||
void dispose() async {
|
||||
await _socket.flush();
|
||||
await _socket.close();
|
||||
_responseRawStreamController.close();
|
||||
_payloadPullStreamController.close();
|
||||
_payloadRawStreamController.close();
|
||||
_responseStreamController.close();
|
||||
_requestStreamController.close();
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 21:41:49
|
||||
* @LastEditTime : 2022-10-14 10:38:31
|
||||
* @LastEditTime : 2022-10-17 22:23:46
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
@ -36,6 +36,7 @@ class HistoryTile extends StatelessWidget {
|
||||
const SizedBox(width: 12,),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
@ -51,6 +52,8 @@ class HistoryTile extends StatelessWidget {
|
||||
),
|
||||
child: Text(
|
||||
message.contentDecoded,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
|
||||
@ -1,19 +1,16 @@
|
||||
/*
|
||||
* @Author : Linloir
|
||||
* @Date : 2022-10-13 21:41:41
|
||||
* @LastEditTime : 2022-10-14 12:04:26
|
||||
* @LastEditTime : 2022-10-18 11:28:17
|
||||
* @Description :
|
||||
*/
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:tcp_client/common/avatar/avatar.dart';
|
||||
import 'package:tcp_client/common/username/username.dart';
|
||||
import 'package:tcp_client/profile/user_profile_page.dart';
|
||||
import 'package:tcp_client/repositories/common_models/userinfo.dart';
|
||||
import 'package:tcp_client/repositories/local_service_repository/local_service_repository.dart';
|
||||
import 'package:tcp_client/repositories/user_repository/user_repository.dart';
|
||||
import 'package:tcp_client/search/cubit/search_cubit.dart';
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ project(runner LANGUAGES CXX)
|
||||
set(BINARY_NAME "tcp_client")
|
||||
# The unique GTK application identifier for this application. See:
|
||||
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
||||
set(APPLICATION_ID "com.example.tcp_client")
|
||||
set(APPLICATION_ID "com.linloir.tcp_client")
|
||||
|
||||
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||
# versions of CMake.
|
||||
|
||||
@ -4,7 +4,7 @@ project(tcp_client LANGUAGES CXX)
|
||||
|
||||
# The name of the executable created for the application. Change this to change
|
||||
# the on-disk name of your application.
|
||||
set(BINARY_NAME "tcp_client")
|
||||
set(BINARY_NAME "LChatClient")
|
||||
|
||||
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||
# versions of CMake.
|
||||
|
||||
@ -89,13 +89,13 @@ BEGIN
|
||||
BEGIN
|
||||
BLOCK "040904e4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "com.example" "\0"
|
||||
VALUE "FileDescription", "tcp_client" "\0"
|
||||
VALUE "CompanyName", "com.linloir" "\0"
|
||||
VALUE "FileDescription", "LChatClient" "\0"
|
||||
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
||||
VALUE "InternalName", "tcp_client" "\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0"
|
||||
VALUE "OriginalFilename", "tcp_client.exe" "\0"
|
||||
VALUE "ProductName", "tcp_client" "\0"
|
||||
VALUE "InternalName", "LChatClient" "\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2022 com.linloir. All rights reserved." "\0"
|
||||
VALUE "OriginalFilename", "LCatClient.exe" "\0"
|
||||
VALUE "ProductName", "LCatClient" "\0"
|
||||
VALUE "ProductVersion", VERSION_AS_STRING "\0"
|
||||
END
|
||||
END
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user