Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

group image sending, share screenshots, some fixes #42

Merged
merged 2 commits into from
Nov 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ dependencies {
//
implementation("org.xerial:sqlite-jdbc:3.43.2.1")
implementation("ca.gosyer:kotlin-multiplatform-appdirs:1.1.1")
implementation("com.sksamuel.scrimage:scrimage-core:4.1.1")
implementation("com.sksamuel.scrimage:scrimage-webp:4.1.1")
}

compose.desktop {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -120,11 +121,14 @@ public static String get_incoming_filetransfer_local_filename(String incoming_fi
{
String result = filter_out_specials_from_filepath(incoming_filename);
String wanted_full_filename_path = VFS_FILE_DIR + "/" + friend_pubkey_str;

// Log.i(TAG, "check_auto_accept_incoming_filetransfer:start=" + incoming_filename + " " + result + " " +
// wanted_full_filename_path);

Log.i(TAG, "get_incoming_filetransfer_local_filename:start=" + incoming_filename + " " + result + " " +
wanted_full_filename_path);
File f1 = new File(wanted_full_filename_path + "/" + result);
try {
Log.i(TAG, "get_incoming_filetransfer_local_filename:file=" + f1.getCanonicalPath());
} catch (Exception e) {
e.printStackTrace();
}

if (f1.exists())
{
Expand Down
130 changes: 128 additions & 2 deletions src/main/java/com/zoffcc/applications/trifa/HelperGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
import static com.zoffcc.applications.trifa.MainActivity.*;
import static com.zoffcc.applications.trifa.TRIFAGlobals.*;
import static com.zoffcc.applications.trifa.TRIFAGlobals.TRIFA_MSG_TYPE.TRIFA_MSG_FILE;
import static com.zoffcc.applications.trifa.ToxVars.TOX_HASH_LENGTH;
import static com.zoffcc.applications.trifa.ToxVars.TOX_MAX_FILENAME_LENGTH;
import static com.zoffcc.applications.trifa.ToxVars.*;

public class HelperGroup {

Expand Down Expand Up @@ -311,4 +310,131 @@ static void delete_group(final String group_identifier)
Log.i(TAG, "delete_group:EE:" + e.getMessage());
}
}

static int send_group_image(final GroupMessage g)
{
// @formatter:off
/*
40000 max bytes length for custom lossless NGC packets.
37000 max bytes length for file and header, to leave some space for offline message syncing.

| what | Length in bytes| Contents |
|------ |-------- |------------------ |
| magic | 6 | 0x667788113435 |
| version | 1 | 0x01 |
| pkt id | 1 | 0x11 |
| msg id | 32 | *uint8_t to uniquely identify the message |
| create ts | 4 | uint32_t unixtimestamp in UTC of local wall clock |
| filename | 255 | len TOX_MAX_FILENAME_LENGTH |
| | | data first, then pad with NULL bytes |
| data |[1, 36701] | bytes of file data, zero length files not allowed!|


header size: 299 bytes
data size: 1 - 36701 bytes
*/
// @formatter:on

final long header = 6 + 1 + 1 + 32 + 4 + 255;
long data_length = header + g.filesize;

if ((data_length > TOX_MAX_NGC_FILE_AND_HEADER_SIZE) || (data_length < (header + 1)))
{
Log.i(TAG, "send_group_image: data length has wrong size: " + data_length);
return -1;
}

ByteBuffer data_buf = ByteBuffer.allocateDirect((int)data_length);

data_buf.rewind();
//
data_buf.put((byte)0x66);
data_buf.put((byte)0x77);
data_buf.put((byte)0x88);
data_buf.put((byte)0x11);
data_buf.put((byte)0x34);
data_buf.put((byte)0x35);
//
data_buf.put((byte)0x01);
//
data_buf.put((byte)0x11);
//
try
{
data_buf.put(hex_to_bytes(g.msg_id_hash), 0, 32);
}
catch(Exception e)
{
for(int jj=0;jj<32;jj++)
{
data_buf.put((byte)0x0);
}
}
//
// TODO: write actual timestamp into buffer
data_buf.put((byte)0x0);
data_buf.put((byte)0x0);
data_buf.put((byte)0x0);
data_buf.put((byte)0x0);
//
byte[] fn = "image.jpg".getBytes(StandardCharsets.UTF_8);
try
{
if (g.file_name.getBytes(StandardCharsets.UTF_8).length <= 255)
{
fn = g.file_name.getBytes(StandardCharsets.UTF_8);
}
}
catch(Exception ignored)
{
}
data_buf.put(fn);
for (int k=0;k<(255 - fn.length);k++)
{
// fill with null bytes up to 255 for the filename
data_buf.put((byte) 0x0);
}
// -- now fill the data from file --
java.io.File img_file = new java.io.File(g.filename_fullpath);

long length_sum = 0;
java.io.FileInputStream is = null;
try
{
is = new java.io.FileInputStream(img_file);
byte[] buffer = new byte[1024];
int length;

while ((length = is.read(buffer)) > 0)
{
data_buf.put(buffer, 0, length);
length_sum = length_sum + length;
Log.i(TAG,"put " + length + " bytes into buffer");
}
}
catch(Exception e)
{
}
finally
{
try
{
is.close();
}
catch(Exception e2)
{
}
}
Log.i(TAG,"put " + length_sum + " bytes TOTAL into buffer, and should match " + g.filesize);
// -- now fill the data from file --

byte[] data = new byte[(int)data_length];
data_buf.rewind();
data_buf.get(data);
int res = tox_group_send_custom_packet(tox_group_by_groupid__wrapper(g.group_identifier),
1,
data,
(int)data_length);
return res;
}
}
131 changes: 131 additions & 0 deletions src/main/java/com/zoffcc/applications/trifa/HelperMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@
import com.zoffcc.applications.sorm.Filetransfer;
import com.zoffcc.applications.sorm.Message;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;

import static com.zoffcc.applications.trifa.HelperFiletransfer.get_incoming_filetransfer_local_filename;
import static com.zoffcc.applications.trifa.MainActivity.*;
import static com.zoffcc.applications.trifa.ToxVars.TOX_HASH_LENGTH;
import static com.zoffcc.applications.trifa.ToxVars.TOX_MESSAGE_TYPE.TOX_MESSAGE_TYPE_HIGH_LEVEL_ACK;
Expand Down Expand Up @@ -267,4 +276,126 @@ public static void set_message_start_sending_from_id(long message_id)
Log.i(TAG, "set_message_start_sending_from_id:EE:" + e.getMessage());
}
}

/**
* Get an image off the system clipboard.
*
* @return Returns an Image if successful; otherwise returns null.
*/
public static Image getImageFromClipboard()
{
Transferable transferable = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
if (transferable != null && transferable.isDataFlavorSupported(DataFlavor.imageFlavor))
{
try
{
// Log.i(TAG, "getImageFromClipboard:"+transferable.getTransferDataFlavors());
// Log.i(TAG, "getImageFromClipboard:I="+(Image) transferable.getTransferData(DataFlavor.imageFlavor));
return (Image) transferable.getTransferData(DataFlavor.imageFlavor);
}
catch (UnsupportedFlavorException e)
{
// handle this as desired
e.printStackTrace();
}
catch (IOException e)
{
// handle this as desired
e.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
}
return null;
}

public static void take_screen_shot_with_selection(final String selected_friend_pubkey)
{
try
{
Log.i(TAG, "CaptureOccured...SelectionRectangle start");
new SelectionRectangle();
final Thread t = new Thread(() -> {
try
{
while (SelectionRectangle.showing)
{
Thread.sleep(20);
}

Thread.sleep(200);
Log.i(TAG, "CaptureOccured...SelectionRectangle done");

try
{
if (!SelectionRectangle.cancel)
{
Log.i(TAG, "CaptureOccured...Screenshot capture");
BufferedImage img = (BufferedImage) Screenshot.capture(SelectionRectangle.capture_x,
SelectionRectangle.capture_y,
SelectionRectangle.capture_width,
SelectionRectangle.capture_height).getImage();

Log.i(TAG, "CaptureOccured...Screenshot capture DONE");

if (img != null)
{
Log.i(TAG, "CaptureOccured...Image");
try
{
Log.i(TAG, "CaptureOccured...Image:003:" + selected_friend_pubkey);

final String friend_pubkey_str = selected_friend_pubkey;

String wanted_full_filename_path =
TRIFAGlobals.VFS_FILE_DIR + "/" + friend_pubkey_str;
new File(wanted_full_filename_path).mkdirs();

String filename_local_corrected = get_incoming_filetransfer_local_filename(
"clip.png", friend_pubkey_str);

filename_local_corrected =
wanted_full_filename_path + "/" + filename_local_corrected;

Log.i(TAG, "CaptureOccured...Image:004:" + filename_local_corrected);
final File f_send = new File(filename_local_corrected);
boolean res = ImageIO.write(img, "png", f_send);
Log.i(TAG,
"CaptureOccured...Image:004:" + filename_local_corrected + " res=" +
res);

// send file
MainActivity.Companion.add_outgoing_file(f_send.getAbsoluteFile().getParent(),
f_send.getAbsoluteFile().getName(), friend_pubkey_str);
}
catch (Exception e2)
{
e2.printStackTrace();
Log.i(TAG, "CaptureOccured...EE2:" + e2.getMessage());
}
}
}
else
{
Log.i(TAG, "CaptureOccured...SelectionRectangle CANCEL");
}
}
catch (Exception e)
{
}
}
catch (Exception e2)
{
}
});
t.start();
}
catch (Throwable e)
{
e.printStackTrace();
Log.i(TAG, "CaptureOccured...EE1:" + e.getMessage());
}
}
}
Loading
Loading