<commit_before>import React, { ReactNode } from "react";
import { connect } from "react-redux";

import * as SnapUtils from "../snapUtils";
import * as Selectors from "../selectors";
import { updateWindowPositions } from "../actionCreators";
import {
  WindowInfo,
  Dispatch,
  WindowPositions,
  AppState,
  WindowId,
} from "../types";
const abuts = (a: SnapUtils.Box, b: SnapUtils.Box) => {
  // TODO: This is kinda a hack. They should really be touching, not just within snapping distance.
  // Also, overlapping should not count.
  const wouldMoveTo = SnapUtils.snap(a, b);
  return wouldMoveTo.x !== undefined || wouldMoveTo.y !== undefined;
};

interface Props {
  container: HTMLElement;
  windowsInfo: WindowInfo[];
  browserWindowSize: { height: number; width: number };
  updateWindowPositions(positions: WindowPositions, center: boolean): void;
  getWindowHidden(windowId: WindowId): boolean;
  windows: { [windowId: string]: ReactNode };
}

class WindowManager extends React.Component<Props> {
  movingAndStationaryNodes(key: WindowId): [WindowInfo[], WindowInfo[]] {
    const windows = this.props.windowsInfo.filter(
      w =>
        this.props.windows[w.key] != null && !this.props.getWindowHidden(w.key)
    );
    const targetNode = windows.find(node => node.key === key);
    if (targetNode == null) {
      throw new Error(`Tried to move a node that does not exist: ${key}`);
    }

    let movingSet = new Set([targetNode]);
    // Only the main window brings other windows along.
    if (key === "main") {
      const findAllConnected = SnapUtils.traceConnection(abuts);
      movingSet = findAllConnected(windows, targetNode);
    }

    const stationary = windows.filter(w => !movingSet.has(w));
    const moving = Array.from(movingSet);

    return [moving, stationary];
  }

  handleMouseDown = (key: WindowId, e: React.MouseEvent<HTMLDivElement>) => {
    if (!(e.target as HTMLElement).classList.contains("draggable")) {
      return;
    }

    if (this.props.getWindowHidden(key)) {
      // The user may be clicking on full screen Milkdrop.
      return;
    }
    // Prevent dragging from highlighting text.
    e.preventDefault();

    const [moving, stationary] = this.movingAndStationaryNodes(key);

    const mouseStart = { x: e.clientX, y: e.clientY };
    const { browserWindowSize } = this.props;

    const box = SnapUtils.boundingBox(moving);

    const handleMouseMove = (ee: MouseEvent) => {
      const proposedDiff = {
        x: ee.clientX - mouseStart.x,
        y: ee.clientY - mouseStart.y,
      };

      const proposedWindows = moving.map(node => ({
        ...node,
        ...SnapUtils.applyDiff(node, proposedDiff),<commit_msg>Don't prevent text selection with preventDefault<commit_after>import React, { ReactNode } from "react";
import { connect } from "react-redux";

import * as SnapUtils from "../snapUtils";
import * as Selectors from "../selectors";
import { updateWindowPositions } from "../actionCreators";
import {
  WindowInfo,
  Dispatch,
  WindowPositions,
  AppState,
  WindowId,
} from "../types";
const abuts = (a: SnapUtils.Box, b: SnapUtils.Box) => {
  // TODO: This is kinda a hack. They should really be touching, not just within snapping distance.
  // Also, overlapping should not count.
  const wouldMoveTo = SnapUtils.snap(a, b);
  return wouldMoveTo.x !== undefined || wouldMoveTo.y !== undefined;
};

interface Props {
  container: HTMLElement;
  windowsInfo: WindowInfo[];
  browserWindowSize: { height: number; width: number };
  updateWindowPositions(positions: WindowPositions, center: boolean): void;
  getWindowHidden(windowId: WindowId): boolean;
  windows: { [windowId: string]: ReactNode };
}

class WindowManager extends React.Component<Props> {
  movingAndStationaryNodes(key: WindowId): [WindowInfo[], WindowInfo[]] {
    const windows = this.props.windowsInfo.filter(
      w =>
        this.props.windows[w.key] != null && !this.props.getWindowHidden(w.key)
    );
    const targetNode = windows.find(node => node.key === key);
    if (targetNode == null) {
      throw new Error(`Tried to move a node that does not exist: ${key}`);
    }

    let movingSet = new Set([targetNode]);
    // Only the main window brings other windows along.
    if (key === "main") {
      const findAllConnected = SnapUtils.traceConnection(abuts);
      movingSet = findAllConnected(windows, targetNode);
    }

    const stationary = windows.filter(w => !movingSet.has(w));
    const moving = Array.from(movingSet);

    return [moving, stationary];
  }

  handleMouseDown = (key: WindowId, e: React.MouseEvent<HTMLDivElement>) => {
    if (!(e.target as HTMLElement).classList.contains("draggable")) {
      return;
    }

    if (this.props.getWindowHidden(key)) {
      // The user may be clicking on full screen Milkdrop.
      return;
    }

    const [moving, stationary] = this.movingAndStationaryNodes(key);

    const mouseStart = { x: e.clientX, y: e.clientY };
    const { browserWindowSize } = this.props;

    const box = SnapUtils.boundingBox(moving);

    const handleMouseMove = (ee: MouseEvent) => {
      const proposedDiff = {
        x: ee.clientX - mouseStart.x,
        y: ee.clientY - mouseStart.y,
      };

      const proposedWindows = moving.map(node => ({
        ...node,
        ...SnapUtils.applyDiff(node, proposedDiff),
{'fraction_non_alphanumeric': 0.13125820363772736, 'fraction_numerical': 0.0, 'mean_word_length': 3.4046242774566475, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5372406', 'n_tokens_mistral': 1629, 'n_tokens_neox': 1579, 'n_words': 434}